3

I am writing an XML parser and am having an issue with the program handling a link. I am attempting to parse an XML hierarchy Settings/Setting then findnode 'Value'. The following is an example of the XML:

<?xml version='1.0' ?>
<Settings xmlns='http://hme.com/Settings.xsd'>
  <Setting SID="0">
    <Name>Store ID</Name>
    <Value>72</Value>
  </Setting>
  <Setting SID="1">
    <Name>Deprecated</Name>
    <Value>0</Value>
  </Setting>
  <Setting SID="8">
    <Name>Open Store Hours Sunday</Name>
    <Value>25200</Value>
  </Setting>

Here is the code I am using to parse the XML

my $doc = $parser->parse_file($settings_file) or die "Couldn't parse timer settings\n";

#Sunday
for my $reviewer ($doc->findnodes('/Settings/Setting[@SID="8"]')) {
  my ($name) = $reviewer->findnodes('Value');
  $name->removeChildNodes();
  $name->appendText('109800');
}

When I remove the xmlns='http://hme.com/Settings.xsd' from the XML file, there is no issue with replacing the value node. Once I enter the link back in the XML, the code stops working and will not update the xml sheet. Is there a way to handle for this link or to remove it so I can properly update the file?

2
  • You might find the "Working with namespaces" section from my tutorial useful. Commented Jan 28, 2020 at 20:05
  • Looking over the page you suggested I believe I am declaring the namespace correcr but am getting an XPath error: Undefined namespace prefix. I used the xpath sandbox and was able to load in my xml and use the query to find the node but when I attempt in my code no luck. This is how im declaring the namespace my $xpc = XML::LibXML::XPathContext->new(); $xpc->registerNs('xsd', 'http://hme.com/Settings.xsd'); Commented Jan 30, 2020 at 16:11

2 Answers 2

3

You ask to find nodes with namespace null and with name Settings. There are no such nodes in the document, so findnodes correctly returns nothing.

You want to find the nodes with namespace http://hme.com/Settings.xsd and with name Settings. You can use the following to achieve that:

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs( s => 'http://hme.com/Settings.xsd' );

for ($xpc->findnodes('/s:Settings/s:Setting[@SID="8"]'), $doc) {
   ...
}
Sign up to request clarification or add additional context in comments.

Comments

0

I was able to get this working using this code.

my $dom = XML::LibXML->load_xml(location => $filename);

my $xpc = XML::LibXML::XPathContext->new($dom);
$xpc->registerNs('xsd',  'http://hme.com/Settings.xsd');

my($match1) = $xpc->findnodes('//xsd:Settings/xsd:Setting[@SID="8"]/xsd:Value');
$match1->removeChildNodes();
$match1->appendText('23400');

5 Comments

If anyone is looking at this in the future and needs help, this tool helped me alot. grantm.github.io/perl-libxml-by-example/_static/xpath-sandbox/…
That's the same thing I posted 3 days earlier (except you made it a lot worse by using // instead of /).
@ikegami sorry I made it "a lot worse" I wasn't getting it to work with your code. Could be user error, I'm still trying to learn.
The code is identical except in two places: 1) You used xsd instead of s as the prefix, but choice of prefix doesn't matter. 2) You used // instead of /, which is very expensive for no reason, and it could lead to incorrect results.
@ikegami thats my bad I guess, like I said I am no expert today and was even less so 3 years ago.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.