[prev in list] [next in list] [prev in thread] [next in thread]
List: perl-xml
Subject: Re: Namespaces and findnodes() in XML::LibXML
From: Steve Hay <steve.hay () uk ! radan ! com>
Date: 2003-01-24 17:27:21
[Download RAW message or body]
Bjoern Hoehrmann wrote:
>* Steve Hay wrote:
>
>
>>I'm trying to retrieve some attribute node values via XPath in
>>XML::LibXML and keep getting nothing. The following test program
>>demonstrates my problem:
>>
>>
>
>
>
>>This outputs nothing instead of "1".
>>
>>From previous postings on this list it looks as though the problem is
>>related to the "xmlns" namespace attribute in the document element.
>>Sure enough, if I remove that then the program works as expected.
>>
>>However, I'm trying to process thousands of existing XML documents which
>>all have such an attribute in the document element, so I can't simply
>>remove this from each file. How do I achieve what I'm trying to do here?
>>
>>
>
>You need to setup a prefix for that namespace. This could be done by
>copying the old document to a new one with such prefix like
>
> my $doc = $parser->parse_string($text);
> my $tdoc = XML::LibXML::Document->new();
> my $troot = $tdoc->createElement('html');
> $troot->setNamespace('http://www.w3.org/1999/xhtml', 'h');
> $tdoc->setDocumentElement($troot);
> $troot->appendChild($_->cloneNode(1)) foreach $root->childNodes;
> $doc = $tdoc;
>
>
In fact, the following similar idea seems to work, without cloning the
document:
use XML::LibXML;
my $doc = <<'EOT';
<?xml version="1.0" encoding="ISO-8859-1" ?>
<foo xmlns="http://www.foo.com">
<bar num="1"/>
</foo>
EOT
my $parser = XML::LibXML->new();
my $dom_doc = $parser->parse_string($doc);
my $doc_elt = $dom_doc->documentElement();
my $nsURI = $doc_elt->namespaceURI();
$doc_elt->setNamespace($nsURI, 'x');
my $xpath = "/x:foo/x:bar/attribute::num";
foreach my $attr ($dom_doc->findnodes($xpath)) {
print $attr->getValue(), "\n";
}
However, I sometimes need to change the XML data and then write the file
back via $dom_doc->toFile(), and the above approach alters the file.
For example, the above would output:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<x:foo xmlns="http://www.foo.com" xmlns:x="http://www.foo.com">
<bar num="1"/>
</x:foo>
I tried resetting the prefix before calling toFile() with
$doc_elt->setNamespace($nsURI); but I still get:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<foo xmlns="http://www.foo.com" xmlns:x="http://www.foo.com">
<bar num="1"/>
</foo>
output.
>A different approach would be to write
>
> *[local-name() = "foo" and
> namespace-uri(.) = "http://www.foo.com"]
>
>instead of 'prefix:foo'.
>
This works better for me. Just changing the $xpath line in my original
test program to
my $xpath =
qq{/*[local-name()="foo"]/*[local-name()="bar"]/attribute::num};
does the job. (There is only ever one namespace involved.)
Thanks for the suggestions.
- Steve
_______________________________________________
Perl-XML mailing list
Perl-XML@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic