在 Perl 中解析 REST api XML 响应主体
Parsing REST api XML response body in Perl
我有两个问题:
1) 我正在尝试解析 GET 请求的响应,add/delete 一个节点并使用 PUT 将其发回。正在使用 XML::LibXML,用于执行此类操作的正确方法。我担心的是,在我用 XML::LibXML 处理后,PUT 会期望内容吗?我尝试使用 XML::Simple 但它没有用。
2) 我正在尝试使用 XML::LibXML 从我从 GET 请求收到的 REST API 响应正文中解析 XML。它找不到任何东西。它在第 16 行失败说 "invalid expression at /"
这是代码。
1 my $disk_name = "Hard disk 2";
2 my $parser = XML::LibXML->new();
3 my $query;
4 my $name="";
5
6 my $doc = $parser->parse_string ($data_xml);
7 my $xpc = XML::LibXML::XPathContext->new($doc);
8 $xpc->registerNs('x', 'http://www.vmware.com/vcloud/v1.5');
9 $xpc->registerNs('y', 'http://schemas.dmtf..');
10 $xpc->registerNs('z','http://www.vmware.com/vcloud/v1.5');
11
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 }
这是 $data_xml 的样子:
<RasdItemsList xmlns="="http://www.vmware.com/vcloud/v1.5" xmlns:rasd="http://schemas....." xmlns:xsi=.......some more text>
<Link rel="edit" type="some text"/>
<Item>
<rasd:Address>0</rasd:Address>
<rasd:Description>SCSI Controller</rasd:Description>
<rasd:ElementName>SCSI Controller 0</rasd:ElementName>
<rasd:InstanceID>2</rasd:InstanceID>
<rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>
<rasd:ResourceType>6</rasd:ResourceType>
</Item>
<Item>
<rasd:AddressOnParent>0</rasd:AddressOnParent>
<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>
<rasd:InstanceID>2000</rasd:InstanceID>
<rasd:Parent>2</rasd:Parent>
<rasd:ResourceType>17</rasd:ResourceType>
</Item>
...... some more <Items>
</RasdItemsList>
我收到了 GET 请求的响应。我将它除以 \n 并将其放入 $data_xml。所以上面的所有行都被附加到一个巨大的字符串 $data_xml 中。
在此先感谢您的帮助。
My concern is would PUT expect the content after I process it with XML::LibXML?
我不知道有问题的 API 是否接受包含 XML 内容的 PUT。为此,您需要查阅 API 文档。
XML::LibXML 确实是完成这项工作的完美工具,但无论您使用什么工具,您都需要了解自己所拥有的 XML 方法。
你只问了一个问题。您是否还想问为什么 XML::LibXML 找不到任何节点?
如果是,原因可能是 xmlns="http://www........ some text"
你太害羞了。这不是任何旧属性,它是一个 XML namespace,文档中可能至少还有一个定义 rasd:
前缀的属性。
除非您设置了 XPath context,否则您的查询 $doc->findnodes('RasdItemsList/Item')
只会查找没有命名空间的元素。一个简单的解决方法是编写: $doc->findnodes('*[local-name()="RasdItemsList"]/*[local-name()="Item"]')
- 这将测试名称而不考虑命名空间。但是,如果您要添加新节点,则需要实际的命名空间。
我有两个问题:
1) 我正在尝试解析 GET 请求的响应,add/delete 一个节点并使用 PUT 将其发回。正在使用 XML::LibXML,用于执行此类操作的正确方法。我担心的是,在我用 XML::LibXML 处理后,PUT 会期望内容吗?我尝试使用 XML::Simple 但它没有用。
2) 我正在尝试使用 XML::LibXML 从我从 GET 请求收到的 REST API 响应正文中解析 XML。它找不到任何东西。它在第 16 行失败说 "invalid expression at /" 这是代码。
1 my $disk_name = "Hard disk 2";
2 my $parser = XML::LibXML->new();
3 my $query;
4 my $name="";
5
6 my $doc = $parser->parse_string ($data_xml);
7 my $xpc = XML::LibXML::XPathContext->new($doc);
8 $xpc->registerNs('x', 'http://www.vmware.com/vcloud/v1.5');
9 $xpc->registerNs('y', 'http://schemas.dmtf..');
10 $xpc->registerNs('z','http://www.vmware.com/vcloud/v1.5');
11
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 }
这是 $data_xml 的样子:
<RasdItemsList xmlns="="http://www.vmware.com/vcloud/v1.5" xmlns:rasd="http://schemas....." xmlns:xsi=.......some more text>
<Link rel="edit" type="some text"/>
<Item>
<rasd:Address>0</rasd:Address>
<rasd:Description>SCSI Controller</rasd:Description>
<rasd:ElementName>SCSI Controller 0</rasd:ElementName>
<rasd:InstanceID>2</rasd:InstanceID>
<rasd:ResourceSubType>lsilogic</rasd:ResourceSubType>
<rasd:ResourceType>6</rasd:ResourceType>
</Item>
<Item>
<rasd:AddressOnParent>0</rasd:AddressOnParent>
<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>
<rasd:InstanceID>2000</rasd:InstanceID>
<rasd:Parent>2</rasd:Parent>
<rasd:ResourceType>17</rasd:ResourceType>
</Item>
...... some more <Items>
</RasdItemsList>
我收到了 GET 请求的响应。我将它除以 \n 并将其放入 $data_xml。所以上面的所有行都被附加到一个巨大的字符串 $data_xml 中。
在此先感谢您的帮助。
My concern is would PUT expect the content after I process it with XML::LibXML?
我不知道有问题的 API 是否接受包含 XML 内容的 PUT。为此,您需要查阅 API 文档。
XML::LibXML 确实是完成这项工作的完美工具,但无论您使用什么工具,您都需要了解自己所拥有的 XML 方法。
你只问了一个问题。您是否还想问为什么 XML::LibXML 找不到任何节点?
如果是,原因可能是 xmlns="http://www........ some text"
你太害羞了。这不是任何旧属性,它是一个 XML namespace,文档中可能至少还有一个定义 rasd:
前缀的属性。
除非您设置了 XPath context,否则您的查询 $doc->findnodes('RasdItemsList/Item')
只会查找没有命名空间的元素。一个简单的解决方法是编写: $doc->findnodes('*[local-name()="RasdItemsList"]/*[local-name()="Item"]')
- 这将测试名称而不考虑命名空间。但是,如果您要添加新节点,则需要实际的命名空间。