user1549994 user1549994 - 6 months ago 3x
Perl Question

Parsing REST api XML response body in Perl

I have two questions:

1) I am trying to parse response of the GET request, add/delete a node and send it back using PUT. Is using XML::LibXML, the right thing to use for doing such operations. My concern is would PUT expect the content after I process it with XML::LibXML? I tried to use XML::Simple and it did not work.

2) I am trying to use XML::LibXML to parse the XML from the REST API response body that I receive from GET request. It is not able to find anything. It is failing on line 16 saying "invalid expression at /"
Here is the code.

1 my $disk_name = "Hard disk 2";
2 my $parser = XML::LibXML->new();
3 my $query;
4 my $name="";
6 my $doc = $parser->parse_string ($data_xml);
7 my $xpc = XML::LibXML::XPathContext->new($doc);
8 $xpc->registerNs('x', '');
9 $xpc->registerNs('y', 'http://schemas.dmtf..');
10 $xpc->registerNs('z','');
12 log("loop thr the nodes");
13 log($doc);
14 foreach my $item ($xpc->findnodes('/x:RasdItemsList/x:Item')) {
15 log("found a match thr libXML");
16 $name = $item->findnodes("/y:rasd:ElementName[text()='$disk_name']");
17 if($name ne '') {
18 log("The name of the node is " . $name->to_literal);
19 $name->setData('New disk');
20 }
21 }

Here is what the $data_xml looks like:

<RasdItemsList xmlns="="" xmlns:rasd="http://schemas....." xmlns:xsi=.......some more text>
<Link rel="edit" type="some text"/>
<rasd:Description>SCSI Controller</rasd:Description>
<rasd:ElementName>SCSI Controller 0</rasd:ElementName>
<rasd:Description>Hard disk</rasd:Description>
<rasd:ElementName>Hard disk 1</rasd:ElementName>
<rasd:HostResource xmlns:ns12="txt" ns12:capacity="59392" ns12:busSubType="lsilogic" ns12:busType="6"></rasd:HostResource>
...... some more <Items>

I get the response from the GET request. I split it by \n and put that in $data_xml. So all the lines above are appended to make a giant string $data_xml.

Thanks in advance for the help.


My concern is would PUT expect the content after I process it with XML::LibXML?

I have no idea if the API in question accepts PUT with XML content. You will need to consult the API documentation for this.

XML::LibXML is indeed a perfectly capable tool for the job, but you do need to know your way round the XML you've got, whatever tool you use.

You only asked one question. Did you also mean to ask why XML::LibXML isn't finding any nodes?

If so, the reason is probably that xmlns="http://www........ some text" you're being so coy about. That's not any old attribute, it's an XML namespace, and there's probably at least one more in the document defining the rasd: prefix as well.

Your query $doc->findnodes('RasdItemsList/Item') will only find elements with no namespace unless you've set the XPath context. A simple workaround would be to write: $doc->findnodes('*[local-name()="RasdItemsList"]/*[local-name()="Item"]') - this will test the name irrespective of the namespace. However you'll need the actual namespace if you're going to be adding new nodes.