gpt4 book ai didi

xml - 如何在具有命名空间前缀的 TXMLDocument 上使用 XPath?

转载 作者:数据小太阳 更新时间:2023-10-29 02:23:40 25 4
gpt4 key购买 nike

我有一个从第三方网络服务器收到的 XML 数据包:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SomeResponse xmlns="http://someurl">
<SomeResult>
.....
</SomeResult>
</SomeResponse>
</soap:Body>
</soap:Envelope>

为了能够跨平台,这个 XML 被加载到 Delphi 的 IXMLDocument 中:

XmlDoc.LoadFromXML(XmlString);

我是 using a solution使用 XPath 查找 XML 节点。该解决方案适用于其他情况,但是当 XML 文档包含命名空间前缀时,它会失败。

我正在尝试访问路径:

/soap:Envelope/soap:Body/SomeResponse/SomeResult

来自链接的答案:

function selectNode(xnRoot: IXmlNode; const nodePath: WideString): IXmlNode;
var
intfSelect : IDomNodeSelect;
dnResult : IDomNode;
intfDocAccess : IXmlDocumentAccess;
doc: TXmlDocument;
begin
Result := nil;
if not Assigned(xnRoot) or not Supports(xnRoot.DOMNode, IDomNodeSelect, intfSelect) then
Exit;
dnResult := intfSelect.selectNode(nodePath);
if Assigned(dnResult) then
begin
if Supports(xnRoot.OwnerDocument, IXmlDocumentAccess, intfDocAccess) then
doc := intfDocAccess.DocumentObject
else
doc := nil;
Result := TXmlNode.Create(dnResult, nil, doc);
end;
end;

它在 dnResult := intfSelect.selectNode(nodePath); 处失败并出现 EOleException: Reference to undeclared namespace prefix: 'soap'

当节点名称具有命名空间前缀时,我该如何进行这项工作?

最佳答案

不要尝试在 XPath 查询中包含命名空间。如果您只需要 SomeResult 节点的文本,那么您可以使用 '//SomeResult' 作为查询。由于某种原因,SomeResponse 父节点上的默认命名空间 xmlns="http://someurl" 上的默认 xml 实现 (msxml) barfs。但是,使用 OmniXML 作为 DOMVendor(= 跨平台并且从 XE7 开始有效 - 感谢@gabr)这有效:

program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
Xml.XmlIntf,
Xml.XMLDoc,
Xml.XMLDom,
Xml.omnixmldom,
System.SysUtils;

const
xml = '<?xml version="1.0" encoding="utf-8"?>'+#13#10+
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'+#13#10+
'xmlns:xsd="http://www.w3.org/2001/XMLSchema"'+#13#10+
'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'+#13#10+
' <soap:Body>'+#13#10+
' <SomeResponse xmlns="http://tempuri.org">'+#13#10+
' <SomeResult>1</SomeResult>'+#13#10+
' </SomeResponse>'+#13#10+
' </soap:Body>'+#13#10+
'</soap:Envelope>';

function selectNode(xnRoot: IXmlNode; const nodePath: WideString): IXmlNode;
var
intfSelect : IDomNodeSelect;
dnResult : IDomNode;
intfDocAccess : IXmlDocumentAccess;
doc: TXmlDocument;
begin
Result := nil;
if not Assigned(xnRoot) or not Supports(xnRoot.DOMNode, IDomNodeSelect, intfSelect) then
Exit;
dnResult := intfSelect.selectNode(nodePath);
if Assigned(dnResult) then
begin
if Supports(xnRoot.OwnerDocument, IXmlDocumentAccess, intfDocAccess) then
doc := intfDocAccess.DocumentObject
else
doc := nil;
Result := TXmlNode.Create(dnResult, nil, doc);
end;
end;

function XPathQuery(Doc : IXMLDocument; Query : String) : String;

var
Node : IXMLNode;

begin
Result := '';
Node := SelectNode(Doc.DocumentElement, Query);
if Assigned(Node) then
Result := Node.Text
end;

var
Doc : IXMLDocument;

begin
DefaultDOMVendor := sOmniXmlVendor;
Doc := TXMLDocument.Create(nil);
try
Doc.LoadFromXML(Xml);
Writeln(Doc.XML.Text);
Writeln(XPathQuery(Doc, '//SomeResult'));
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Doc := nil;
Readln;
end.

关于xml - 如何在具有命名空间前缀的 TXMLDocument 上使用 XPath?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30687619/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com