473,748 Members | 2,328 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Need help with PHP DOMXML - get_elements_by _tagname

I'm having some issues with PHP DOMXML - in particular the
get_elements_by _tagname method. Now, the PGP docs on this are, well,
sparse, so maybe I'm just doing something stupid. I thought this
method would behave like the 'findnodes' XML method in Perl. Namely
that you can pass it an xpath statement and it will find nodes that
match:
$array = $node->get_elements_b y_tagname($xpat h);
This is long so here's a pagebreak:

And, indeed, this seems to have worked when I've used it in the past.
But I'm working on a more complex system now which does a lot more
sub-node access, etc, and it is failing on me. I put together this
example to demonstrate the failure modes I'm experiencing.

----------------------------------------------------------------------
<?php
if (PHP_OS == "WIN32" || PHP_OS == "WINNT") {
define('EOL', "\r\n");
}
else {
define('EOL', "\n");
}
header("Content-Type: text/plain");
print PHP_VERSION . EOL;

$xml =
'<TestDoc>
<level1>
<level2>
<level3>
<level4>
<fubar>fubar</fubar>
<fubaz>fubaz</fubaz>
</level4>
</level3>
</level2>
</level1>
</TestDoc>';

if (!$domResponse = domxml_open_mem ($xml)) {
print("failed!" );
}

print pcGetField(&$do mResponse, "fubar") . EOL;

lookup(&$domRes ponse);

function lookup($domResp onseRef) {
print $domResponseRef->dump_mem();
$node =
$domResponseRef->get_elements_b y_tagname("leve l4");
$node = $node[0];
print_r($node);
print pcGetField2(&$n ode, "//fubar") . EOL;
print pcGetField(&$do mResponseRef, "fubar") . EOL;
print pcGetField(&$no de, "fubar") . EOL;
$node =
$node->get_elements_b y_tagname("fuba r");
print $node[0]->get_content( ) . EOL;
$node = $node[0];
print_r($node);
}

function pcGetField($nod eRef, $tag) {
if(!isset($node Ref)) {
print("pcGetFie ld: node is blank [" . $tag . "]");
return "";
}
$node = $nodeRef->get_elements_b y_tagname($tag) ;
$node = $node[0];
return $node->get_content( );
}

function pcGetField2($no deRef, $tag) {
if(!isset($node Ref)) {
print("pcGetFie ld: node is blank [" . $tag . "]");
return "";
}
$xpath = xpath_new_conte xt($nodeRef);
$node = &xpath_eval($xp ath, $tag);
$node = $node->nodeset[0];

return $node->get_content( );
}
?>
----------------------------------------------------------------------

With it like this everything is fine:
----------------------------------------------------------------------
4.2.2
fubar
<?xml version="1.0"?>
<TestDoc>
<level1>
<level2>
<level3>
<level4>
<fubar>fubar</fubar>
<fubaz>fubaz</fubaz>
</level4>
</level3>
</level2>
</level1>
</TestDoc>
DomElement Object
(
[type] => 1
[tagname] => level4
[0] => 3
[1] => 137395784
)
fubar
fubar
fubar
fubar
DomElement Object
(
[type] => 1
[tagname] => fubar
[0] => 2
[1] => 138335176
)
----------------------------------------------------------------------

You see, I'm jumping down to 'level4' so fubar is an immediate child
node. But if I start from *anywhere* except the root node or the
immediate parent, it fails. So if I change:
$node = $domResponseRef-&gt;get_element s_by_tagname("l evel4");
to
$node = $domResponseRef-&gt;get_element s_by_tagname("l evel1");
I get:
----------------------------------------------------------------------
4.2.2
fubar
<?xml version="1.0"?>
<TestDoc>
<level1>
<level2>
<level3>
<level4>
<fubar>fubar</fubar>
<fubaz>fubaz</fubaz>
</level4>
</level3>
</level2>
</level1>
</TestDoc>
DomElement Object
(
[type] => 1
[tagname] => level1
[0] => 3
[1] => 138064304
)
fubar
fubar
<br />
<b>Fatal error</b>: Call to a member function on a non-object in
<b>/home/megazone/scripts/PHP/Kiosk/test.php</b> on line <b>56</b><br />
----------------------------------------------------------------------

Note that the it works when checking from the docroot and later when
using xpath_eval and from the reference to the doc root - but fails
the first time you try it from the subnode. It will fail with
TestDoc, level1, level2, and level3. it will fail if I try
get_elements_by _tagname("fubar "), get_elements_by _tagname("//fubar"),
etc. It also fails if you're at say level3 and try to look for
"level4/fubar". I think I've tried every combination I can think of.

So is this just a limitation that it only works when working with the
root node of the document or when looking for an immediate child of
the current node? What the heck am I not seeing?

Thanks.

-MZ, RHCE #80619929990054 1, ex-CISSP #3762
--
<URL:mailto:meg azoneatmegazone .org> Gweep, Discordian, Author, Engineer, me.
"A little nonsense now and then, is relished by the wisest men" 508-755-4098
<URL:http://www.megazone.or g/> <URL:http://www.eyrie-productions.com/> Eris

Jul 17 '05 #1
4 6348
I had a quick skim read of your post (as it was quite long) and it seems
like you don't check to see if get_elements_by _tagname() is even
returning at least one node.

instead of
$node = $node[0];

you should have
if(count($node) ) {
$node=$node[0];
...
$node =
$node->get_elements_b y_tagname("fuba r");
print $node->get_content( ) . EOL;
}
else {
$node = null;
print "There was no level4 element!\n";
}

and also in your function you are using isset() to test if it is a node.
not gonna work.

if(!isset($node Ref))

well of course it will exist. it will exist no matter what is in it
because it is in the function call. The line should be

if(is_object($n odeRef))

this would be an improvement. It would be even better if you tested it
using the is_a() function inside the object test.

DOM can be laboursome. However, it is definately the best way to create
XML data. DOM is fairly low-level in terms of describing a document,
which is why I've written a library which attempts to provide higher
level functionality for app designers.
http://xao-php.sf.net

There is a method to fetch one element based on it's name
http://xao-php.sourceforge.net/api/X...thodndGetOneEl

There is a method for getting an array of nodes from an XPath query
http://xao-php.sourceforge.net/api/X...thodarrNdXPath

These are basically shortcuts to having to write low-level DOM, but they
also do obligatory/mundane sanity checks that you are missing here.
http://xao-php.sourceforge.net/api//....php.html#a392

XAO is for object oriented programmers who would rather leverage code
than have to re-invent the basics every time.

XAO allows you to declare call-back functions based on element names
and/or XPath queries. This provides a custom-tag facility in addition to
DOM functionality.
http://xao-php.sourceforge.net/api/X...cessCustomTags


Jul 17 '05 #2
Terence <tk******@fastm ail.fm> shaped the electrons to say:
I had a quick skim read of your post (as it was quite long) and it seems
like you don't check to see if get_elements_by _tagname() is even
returning at least one node.
In the example I did, no, I didn't bother with any real error
checking. I wrote it solely to illustrate the problem I'm having with
a much larger codebase. I stripped most of that stuff to try to keep
the sample from being monsterous. The overall codebase is a few
thousand lines.
and also in your function you are using isset() to test if it is a node.
not gonna work.

if(!isset($nod eRef))
Actually that does work. If you do the lookup and get 0 results, then
set the node to the 0th element of the array, it is null. And the
isset check does catch passing in an unset node. I've had it happen
in the production code. But I'll check is_object and is_a, sounds
like they may do more appropriate checks.
DOM can be laboursome. However, it is definately the best way to create
XML data. DOM is fairly low-level in terms of describing a document,


I know, I've worked with DOM for a while. This codebase already
exists in other languages, the PHP version is more recent. One of the
over riding requirements is keeping the code structures of the various
implementations of the code similar. The Perl, ASP and CF
implementations all use DOM. I wrote the Perl code before we added
PHP as a supported platform. The Perl is using XML::LibXML for this,
which uses libxml2 - same as DOMXML. CF5 and ASP use MSXML, CF MX
uses the built in XML handler CF MX provides.

It was working in our 2.5.5 revision - the 2.6.0 revision restructured
the functions and introduced more pass-by-reference calls, and more
work from subnodes instead of always working from the root node. It
worked fine in all the other languages - but when the changes were
made to PHP, it stopped working. And it stems from this function.

Doing more digging since I posted (pretty much what I've been doing
all day), it looks like I'm going to have to change anyway. While
get_elements_by _tagname worked with xpath in some situations, the
response to one bug report at php.net indicates this has been changed
in newer versions of PHP and the method will *not* support xpath. The
reply indicated that if you want to use xpath, you need to explicitly
use the xpath methods. Unfortunate, since the other languages support
xpath in their equivalent methods (ASP/VB's SelectSingleNod e, Perl's
findnodes, etc). But I think the simplest solution may be replacing
all the occurances of get_elements_by _tagname with the xpath
functions. At least all the occurances that break at this time.

Since the code is a sample framework that goes out to customers one of
the general requirements is to try not to depend on being too current
on the releases and trying to stick to libraries that are as common as
possible. XML handling is mandatory since the framework communicates
with a kiosk system that speaks XML only. Since the requirement for
XML was there, all of the configs and such are also stored in XML
since it is a nice format.

I'm looking forward to PHP5 since the XML support is a fundamental
feature. I only got back into PHP a few months ago (I had used it in
PHP3 days, and played with it in the PHP/FI days) when we added PHP to
our list of supported platforms. The initial port of Perl 2.5.5 to
PHP 2.5.5 actually went extremely smoothly. I was kind of surprised
to run into this trouble with 2.6.0 after that experience. There are
two main contexts for the framework - one is working, the other is not.

-MZ, RHCE #80619929990054 1, ex-CISSP #3762
--
<URL:mailto:meg azoneatmegazone .org> Gweep, Discordian, Author, Engineer, me.
"A little nonsense now and then, is relished by the wisest men" 508-755-4098
<URL:http://www.megazone.or g/> <URL:http://www.eyrie-productions.com/> Eris
Jul 17 '05 #3
I assumed you were asking why you got the exception about trying to use
a method on a non-object.

The fact that xpath doesn't work with get_elements_by _tagnam() is
testiment to the fact that a standards based approach neccesitates
implementing only features of the lowest common denominator. If you are
writing a cross-platform (ie. multi language) framework, you will always
have these limitations. While PHP5 will be using libxml2, I don't know
if this means it will support XPath in get_elements_by _tagnam(). The
behaviour is non-standard.

Jul 17 '05 #4
Terence <tk******@fastm ail.fm> shaped the electrons to say:
I assumed you were asking why you got the exception about trying to use
a method on a non-object.
That was one symptom - why goes get_elements_by _tagname() work if you
start from the docroot or the immediate parent, but no where in
between? Perhaps this is fixed in a later version of PHP - from the
docs it sounds like it *should* recurse the structure no matter where
you start from.
The fact that xpath doesn't work with get_elements_by _tagnam() is
It does appear to work some of the time, and one of the comments left
in the online PHP documentation illustrates using XPath:
http://us2.php.net/manual/en/functio...by-tagname.php

That, and other examples I found when looking for sample code, seemed
to indicate XPath was valid. It seemed to make sense as that also fit
with the behavior of other languages.

But this evening I found this:
http://bugs.php.net/bug.php?id=26205

From one of the comments:
---
ch****@php.net

you are using xpath-expressions and not simple element-names. This may
had worked with older php versions, but the internal code was changed
later.

If you want to use something like "timeopen/year" then use the
appropriate xpath methods (see manual..)
---

So it sounds like the right thing to do is switch to straight tagnames
where possible, and use the xpath functions where it isn't.
implementing only features of the lowest common denominator. If you are
writing a cross-platform (ie. multi language) framework, you will always
It is part of a payment system - the framework exists in different
languages because it is the piece merchant can integrate with their
backend. So we provide it in whatever language the merchant is using
for their site. Before I joined the company a year ago it was
basically a Windows shop so it was ASP and CF, I did the Perl and PHP
implementations . JSP is on the roadmap. But I readily admit I'm
still learning PHP - I tend to implement any new features in Perl
first since that's my primary language, and then port it to PHP. For
the most part that's worked rather well, the language structures are
close enough that a lot of the 'porting' can be done with emacs
regexps. Looks like this is one of the 'gotchas' though - it looked
like 'get_elements_b y_tagname' was a drop in replacement for
'findnodes', but that no long seems to be the case.
have these limitations. While PHP5 will be using libxml2, I don't know
if this means it will support XPath in get_elements_by _tagnam(). The
behaviour is non-standard.


Based on what I found tonight, it sounds like the move is away from
allowing XPath in the PHP functions - except for the xpath_eval, etc,
family.

I've probably made my share of newbie errors in the PHP port - I know
I used 'isset' in a number of places and some of them I caught and
made 'is_object', but some are probably still off. Like most things,
it was done with the "we need it yesterday" mandate, so I didn't have
a lot of time to refresh my PHP knowledge. I picked up O'Reilly's
Programming PHP, the PHP.net documentation, and hit the ground
running. ;-)

-MZ, RHCE #80619929990054 1, ex-CISSP #3762
--
<URL:mailto:meg azoneatmegazone .org> Gweep, Discordian, Author, Engineer, me.
"A little nonsense now and then, is relished by the wisest men" 508-755-4098
<URL:http://www.megazone.or g/> <URL:http://www.eyrie-productions.com/> Eris
Jul 17 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
2031
by: Susanne Klemm | last post by:
Hello! I am working with the XML-DOM-Extension. I want to change the content of a variable in a XSL-Document. The following testscript works well. $dom = domxml_open_file(getcwd()."/einzelnes_item.xsl") $elements = $dom->get_elements_by_tagname("table") echo count($elements)." Elements<br/>"; for ($i=0;$i<count($elements);$i++)
0
3088
by: erickrefener | last post by:
Hi, I need to use a 'socket server' to use with Flash and its 'xmlsocket()' function. I've found Patserver (http://www.php-tools.de/site.php?&PHPSESSID=c51bf69665ec19a00662ef85a27f99c7&file=/patServer/overview.xml) which seems to be pretty much simple and which would perfectly feet my needs, but when I execute the main script I get an error : Fatal error: Call to undefined function: xmldoc() ...
3
3234
by: srommens | last post by:
Hello, When I try to do : URI = <xsl:value-of select="//@URI"/><br/> <xsl:if test = "//@URI != '5-42922'">not equal</xsl:if><br/> <xsl:if test = "//@URI = '5-42922'">equal</xsl:if><br/> The result is :
2
2024
by: Joel Witherspoon | last post by:
I'm generating an xml file using PHP DOMXML . I'm able to create and edit the file fine, however the formatting of my file is off. Instead of being the standard xml: <?xml version="1.0"> <root> <element> </element> </root> I am getting:
5
3992
by: bissatch | last post by:
Hi, I have just managed to install DOMXML on my apache/PHP setup. I am running PHP 4.3.0 and Apache2. $xmldoc = domxml_open_file("inc/menu.xml", DOMXML_LOAD_DONT_KEEP_BLANKS); When I try to load an XML file using the above, it gives me the following error:
1
1803
by: bizt | last post by:
Hi Please forgive the length of this post and bear with me. I am having trouble between two different servers and the same DOMXML code. Basically I am trying to run a script that will: 1) load an XML file as a variable object ($xml_doc):
2
1448
by: KubixKiller | last post by:
Hello, I use the following XML-file to store some useless facts I want to display using PHP. I wrote some PHP code to generate HTML, because I do not have any knowledge of stylesheets etc etc. The problem arises that the php-function next_sibling from the DOMXML library doesn't seem to do what it should. See the code later in this message. Look at the lines below the comment line : # Cycle all item-elements
3
1935
by: CptDondo | last post by:
Does anyone know how to specify the format for the domxml->dump_file method? I am at a loss; my document is being dumped as one great big long line, and I want to insert line breaks and spaces so that it is human readable. --Yan
2
3316
mageswar005
by: mageswar005 | last post by:
hi, I installed php5 in linux server, inside the usr/lib/php5 the domxml.so file is missing,without domsml.so i can'nt able to import scorm packages. How can i install domxml.so to my linux server? Any one give me the domxml.so download link. Regards mageswaran
0
8822
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
9310
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9236
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8235
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6072
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4592
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4863
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3298
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2774
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.