Why am I getting an "Invalid predicate" error from getElementsByTagName?

I have the following XML:

<config> <version general="1.2.3"> <subtype type="a" version="1.2" /> <subtype type="b" version="3.6" /> ... </version> ... </config> 

I have code in Perl to get the node configuration from a database.

After that, if I try the following:

 my $elem = $cfg->getElementsByTagName("version"); my $generalVer = $elem ? $elem->get_node(1)->getAttribute("general") : undef; 

everything is working fine, $generalVer contains 1.2.3 as expected.

But if I try this:

 my $elem = $cfg->getElementsByTagName("version/subtype[@type='a']"); my $aVersion = $elem ? $elem->get_node(1)->getAttribute("version") : undef; 

Failed to execute the message "Invalid predicate".

Can someone help with this problem?

+4
source share
4 answers

Thanks everyone for the answers.

Shortly after I asked the question, someone replied that the problem is in one quote, and if I use double quotes, this will work. those. @type= " a " instead of @type= ' a ' .. p>

Well, that really decided. But when I tried to mark his answer as the correct answer, I found out that he deleted it.

So, I send the answer myself, just for the record.

The following code works very well:

 my $elem = $cfg->getElementsByTagName("version/subtype[@type=\"a\"]"); my $aVersion = $elem ? $elem->get_node(1)->getAttribute("version") : undef; 

Thanks.

+4
source

I strongly suspect that "version/subtype[@type='a']" not, in fact, a tag name. This is similar to an XPath request.

I assume that you are using something like XML :: DOM to parse this XML. If you want to use XPath, you can use XML :: DOM :: XPath , which adds XPath support.

For instance,

  use XML::DOM; use XML::DOM::XPath; ... my $elem = $cfg->findnodes( q{//version/subtype[@type='a']} ); 
+9
source

The getElementsByTagName method expects a name; I don't think it supports XPath. To use XPath queries, you will need to use the XML :: XPath module instead of XML :: DOM.

Here is an example using XML :: XPath:

 #!/usr/bin/perl use strict; use warnings; use XML::XPath; my $xml = <<END; <config> <version general="1.2.3"> <subtype type="a" version="1.2" /> <subtype type="b" version="3.6" /> </version> </config> END my $xp = XML::XPath->new(xml => $xml); my $nodeset = $xp->find("//version/subtype[\@type='a']"); foreach my $node ($nodeset->get_nodelist) { my $version = $node->getAttribute("version"); print "Version: $version\n"; } 

Note that you need to avoid @ in subtype[\@type='a' , otherwise Perl will look for an array named @type .

+4
source

You must use XPath to select an item using the path, or do it in two steps. getElementsByTagName () can only process tag names, not element paths. XPath is preferable if you are doing conditional allocations (which you use with "@type = 'a").

+1
source

All Articles