Xml Delphi将子元素添加到XPath结果
难以区分IDOMNode和IXMLNode。 我想将文档中的子元素附加到使用XPath选择的节点 我尝试的是: 努力1: 我从Xml Delphi将子元素添加到XPath结果,xml,delphi,xpath,Xml,Delphi,Xpath,难以区分IDOMNode和IXMLNode。 我想将文档中的子元素附加到使用XPath选择的节点 我尝试的是: 努力1: 我从IDOMNodeSelect.selectNodes(表达式)中获得一个XPath结果节点N:IDOMNode 如果我使用 intfDocAccess : IXmlDocumentAccess; doc: TXMLDocument; ... if Supports( N.OwnerDocument, IXmlDocumentAccess, intfDocAccess) t
IDOMNodeSelect.selectNodes(表达式)中获得一个XPath结果节点N:IDOMNode代码>
如果我使用
intfDocAccess : IXmlDocumentAccess;
doc: TXMLDocument;
...
if Supports( N.OwnerDocument, IXmlDocumentAccess, intfDocAccess) then
doc := intfDocAccess.DocumentObject
else
doc := nil;
NodeAsIXMLNode := TXmlNode.Create( N, nil, doc );
…然后向其中添加子项会引发访问冲突。可能NodeAsIXMLNode甚至不在原始文档中,它只是为了类型兼容性而创建的副本
努力2:
尝试直接将子节点添加到XPath结果节点:
XMLNode := XmlDoc.CreateElement( 'tag', '' );
N.appendChild( XMLNode as IDOMNode );
它抛出不支持的接口。我感觉xpath结果IDOMNode节点也不是原始IXMLDocument的成员,只是一些结果副本。只是猜测而已
那么,如何使用xpath选择一个节点,然后向其附加一个子元素节点呢?
因此,我的原始IXML文档得到更新
更新:
遍历整个xml文档树,并将IXMLNode的DOMNode与XPath结果DOMNode进行比较,发现DOMNode也不起作用——原始文档中不包含XPath结果节点。尝试了msxml、adom和omnixml实现/XE7/
更新2:
设法使用第一种方法,只需替换
doc := nil;
与
在转换器功能中 我不确定这是否有用,但假设您有一个XML文档
<Content>
<Clients>
<Client>
<ID value="88"/>
<Forename value="John"/>
<Surname value="Smith"/>
</Client>
</Clients>
</Content>
此代码使用D7附带的MSXML.Pas导入单元,并使用当时最新的MSXML.DLL版本(C:\WINDOWS\SYSTEM\MSXML.DLL)生成
就我个人而言,我从未发现Delphi的“抽象”TXmlDocument有帮助——我发现使用MSXML的对象更容易。Ymmv…XPath仅用于搜索,不用于操作文档。无法将XPathIDOMNode
转换回原始的IXMLNode
,并且selectNodes()
不报告在文档中找到DOM节点的位置。迭代文档以查找匹配的节点违背了使用XPath的目的,您也可以首先手动迭代文档,而不使用XPath。谢谢,也许吧,但既然XPath很方便,为什么不这样使用呢?当然,我可以以一种同时使xpath结果无效的方式操作文档,但我没有。请参阅更新2了解当前的工作方式。请注意doc:=TXMLDocument(\u xpathdoc)代码>被视为“不安全”类型转换,如果转换失败,将返回nil
。“安全”强制转换是使用作为
运算符,因此如果强制转换失败,它会引发异常:doc:=\u xpathdoc作为TXMLDocument代码>。请参阅Embarcadero的DocWiki。谢谢,根据您的建议更新了上述代码。
<Content>
<Clients>
<Client>
<ID value="88"/>
<Forename value="John"/>
<Surname value="Smith"/>
</Client>
</Clients>
</Content>
procedure TForm1.btnLoadClick(Sender: TObject);
var
XmlDoc: IXMLDOMDocument;
NodeList : IXmlDOMNodeList;
Node,
NewNode : IXmlDomNode;
E : IXmlDomElement;
TextNode : IXMLDOMText;
Value : String;
I : Integer;
begin
Memo2.Lines.Clear;
XmlDoc := CoDOMDocument.Create; //CreateOleObject('Microsoft.XMLDOM') as IXMLDOMDocument;
XmlDoc.Async := False;
XmlDoc.LoadXML(Memo1.Lines.Text);
if xmlDoc.parseError.errorCode <> 0 then
raise Exception.Create('XML Load error:' + xmlDoc.parseError.reason);
NodeList := XmlDoc.documentElement.SelectNodes(edPathQuery.Text);
if NodeList.length > 0 then begin
E := XMLDoc.createElement('Added');
// E.nodeValue := 'Something'; Note the error this raises. Using the
// TextNode as below avoids this
NewNode := E as IXMLDomNode;
TextNode := XMLDoc.createTextNode('Data');
NewNode.appendChild(TextNode);
NodeList.item[0].appendChild(NewNode);
end;
Memo2.Lines.Text := XMLDoc.documentElement.xml;
end;