【问题标题】:How do I return CDATA content from XML using IXMLNode (delphi exception)如何使用 IXMLNode 从 XML 返回 CDATA 内容(delphi 异常)
【发布时间】:2019-03-28 22:04:48
【问题描述】:

我有一个 XML 文档,我尝试使用 Delphi 和 XMLDoc 提取值。大多数零件都可以正常工作。我使用 IXMLNode 来选择节点文本。但我有一个部分可能包含 CDATA。当我尝试获取它时,这总是会引发异常。

我的 XML(相关部分)与此类似

    <a>valuea</a>
    <b>My b value</b>
    <c>![CDATA[My cdata text goes here
It may have linefeed inside
like this
and I need to get all lines WITH linefeeds
]]>
</c>

我今天的代码是这样的:

  var
     IDoc: IXMLDocument;
     INode: IXMLNode;
     XPathText : string;
     i         : integer;

              // From a post in Embarcadero's Delphi XML forum.
              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;
// --------------------------------------------
   begin
       IDoc:= LoadXMLDocument(edtXMLFileName.Text);
       idoc.ParseOptions := [poPreserveWhiteSpace];
       XPathText := './/path/to/c';   // as per example above, this is my CDATA

        INode := selectnode(IDoc.DocumentElement, xpathtext);

        showmessage(inode.text);  // <<< Notice: .text not .XML FAILS for XML with exception.


   end;

正确的方法是什么

  • 获取 CDATA 值
  • ..同时保留任何换行符
  • 我不需要标签或 CDATA 标签。只是满足。

编辑 当前状态(更正):如果我使用 IXMLNode 的 .XML 值,我会得到包括 CDATA 等在内的完整标签:

    <c>![CDATA[My cdata text goes here
It may have linefeed inside
like this
and I need to get all lines WITH linefeeds
]]>
</c>

但如果我使用 .text,delphi 会抛出异常。

"Element does not contain a single text node."

有人建议here 使用XMLTextReader,但我需要到处查询,不能进行前向只读。

我的备份计划是使用单独的函数来删除如上返回的 XML / CDATA 标记,但这并不漂亮。

【问题讨论】:

  • 您到底遇到了什么异常?在哪条线上?
  • Remy:见上文,为了清楚起见,我编辑了问题。我可以得到完整的“c”标签,也可以得到一个例外。

标签: delphi


【解决方案1】:

CDATA 节点不同于文本节点。您不能使用 IXMLNode.Text 属性来读取 CDATA 节点的内容。这是documented behavior

Text 用于使用 IsTextElement 属性为 true 的节点。 如果 IsTextElement 为 false,则如果该节点没有子节点,Text 的值为空字符串。

设置Text 是这种情况导致IsTextElement 为真的节点。

如果节点有子节点(除了单个 DOM 文本节点),读取或设置 Text 会导致异常。

您需要改用IXMLNode.NodeValue 属性,它可以读取CDATA 和文本内容:

ShowMessage(INode.NodeValue);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    • 2015-09-08
    • 2013-03-28
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 2013-03-06
    相关资源
    最近更新 更多