Delphi将子元素添加到XPath结果中

时间:2017-01-29 16:55:02

标签: xml delphi xpath

很难与IDOMNode和IXMLNode区分开来。 我想将文档中的子元素追加到使用XPath选择的节点。

我尝试了什么:

努力1:

我从IDOMNodeSelect.selectNodes(expression);获得了一个XPath结果节点 N:IDOMNode 如果我使用

将其转换回IXMLNode
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选择节点,然后将子元素节点附加到它? 所以我原来的IXMLDocument会更新。

更新的 遍历整个xml文档树并将IXMLNode的DOMNode与XPath结果进行比较DOMNode也无法正常工作 - 事实证明,XPath结果节点不包含在原始文档中。尝试了msxml,adom和omnixml实现/ XE7 /

更新2: 管理使用第一种方法,只需替换

doc := nil;

doc := _xpathdoc as TXMLDocument; // _xpathdoc : the IXMLDocument

在转换器功能中。

1 个答案:

答案 0 :(得分:0)

我不确定这是否有帮助,但假设您有一个XML文档

<Content>
  <Clients>
    <Client>
      <ID value="88"/>
      <Forename value="John"/>
      <Surname value="Smith"/>
    </Client>
  </Clients>
</Content>

加载到TMemo和TEdit,edPathQuery,包含/Content/Clients。然后,以下代码将找到Clients节点并向其附加新节点+值

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;

此代码使用D7附带的MSXML.Pas导入单元,并使用当时最新的MSXML.DLL版本生成(C:\ WINDOWS \ SYSTEM \ MSXML.DLL)。

就我个人而言,我从未发现过Delphi&#34;#34;#34;#34; TXmlDocument很有帮助 - 我发现使用MSXML的对象更容易。 Ymmv ......