我正在尝试解析来自 SOAP Web 服务的响应,但部分数据具有无效的 xmlns 元素,我认为它给我带来了无穷无尽的麻烦。
我正在使用的 XML 部分如下。
<soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<ResponseData xmlns="http://www.example.com/WebServices/Schemas/1">
<ResponseDataResult>
<Messages xmlns="http://www.example.com/WebServices/Schemas/2">
<Message>...</Message>
</Messages>
</ResponseDataResult>
...
</ResponseData>
</soap:Body>
soap:Body 节点中的 xmlns URI 是可以的,它在 ResponseData 中的那个无效,它指向一个不存在的文档。应该注意的是,Web 服务不在我的控制之下,因此解决此问题是不可能的:(。
我的 Delphi (2007) 代码目前看起来像这样。
var l_tmp,l_tmp2,FSOAPBody:IXMLNode;
begin
...
FSOAPBody := FSOAPEnvelope.ChildNodes.FindNode('Body','http://schemas.xmlsoap.org/soap/envelope/');
//returns the xml above.
if (FSOAPBody = nil) then exit;
l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData','');
if (l_tmp = nil) or (not l_tmp.HasChildNodes) then exit;
l_tmp2 := l_tmp.ChildNodes.FindNode('ResponseDataResult','');
...
end;
在上面的代码中,我不得不将空白命名空间 url 添加到
FindNode('ResponseData','')
没有它的代码,它不会找到任何东西并返回 nil,但是它会返回预期的 XML。问题是下一个查找节点(
ChildNodes.FindNode('ResponseDataResult','')
)在尝试访问 l_tmp 的 ChildNodes 时引发访问冲突,我可以使用 l_tmp.xml 查看 xml 并看到它是我期望的 XML。我怀疑这是由于缺少命名空间,所以我试图删除它,但收到更多错误消息,说它是一个只读属性。
无论如何要删除 xmlns 属性或选择节点,而不管 NS 是否存在?或者我在做这个错误吗?
最佳答案
不希望所有命名空间 URI 都指向实际资源。它们主要用作唯一标识符,因此来自多个来源的 XML 可以使用相同的名称而不会相互干扰。它们不需要指向描述命名空间的有效元素和属性值的模式; XML 甚至不需要这样的模式存在。
如果你想在不考虑命名空间的情况下搜索元素,那么调用 FindNode
的单参数版本.
l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData');
双参数版本需要一个命名空间,当您指定一个空字符串时,这意味着您只请求具有空命名空间的节点。因为您显然知道命名空间是什么,所以无论如何您都可以调用两个参数版本,就像您使用它来获取 body 元素一样:
l_tmp := FSOAPBody.ChildNodes.FindNode('ResponseData',
'http://www.example.com/WebServices/Schemas/1');
关于xml - Delphi - IXMLNode 中的命名空间 URI 无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/828673/