【问题标题】:What's going on with these XML nodes named "#text"?这些名为“#text”的 XML 节点是怎么回事?
【发布时间】:2010-07-21 19:02:33
【问题描述】:

我有一些简单的 XML 处理代码,它们应该根据属性值定位传入节点的子节点:

function GetNodeByAttributeValue(
  const AParentNode: IXMLNode;
  const AttributeName: string; AttributeValue: Variant): IXMLNode;
var
  i: integer;
  value: Variant;
begin
  result := nil;
  if (not Assigned(AParentNode)) or (AttributeName = '') then
    exit;
  for i := 0 to AParentNode.ChildrenCount-1 do
  begin
    result := AParentNode.Children[i];
    value := result.GetAttributeValue(AttributeName, UnAssigned);
    if not VarIsEmpty(value) then
      exit;
  end;
  result := nil;
end;

很简单,对吧?但是当我尝试运行它时,在某些情况下它会因访问冲突而崩溃。这是发生了什么:

IXML* 实现由 RemObjects SDK 库提供。 result.GetAttributeValue 调用uROMSXMLImpl.TROMSXMLNode.GetAttributeValue,它调用TROMSXMLNode.GetAttributeByName,它说

  node := fNode.attributes.getNamedItem(anAttributeName);

这会崩溃,因为 fNode.attributes 返回 nil。据我了解,这不应该发生。

奇怪的是,回到原始函数中的for循环,AParentNode.ChildrenCount返回3。但是原始XML文档中的节点只有一个子节点。它符合我正在寻找的标准。

<ParentNode>
  <namespace:ChildNode name="right-name">

但是AParentNode.ChildrenCount 返回 3。我在调试器中打开它们并得到这个:

AParentNode.Children[0].name: '#text'
AParentNode.Children[1].name: 'namespace:ChildNode'
AParentNode.Children[2].name: '#text'

这些“#text”节点到底是什么?它们不在 XML 文档中,我也没有编写任何代码来插入它们。它们为什么在那里,为什么它们有问题,我能做些什么来防止它们搞砸我的属性搜索?

【问题讨论】:

    标签: xml delphi remobjects


    【解决方案1】:

    文本节点是解析器返回的空白。
    &lt;namespace:ChildNode name="right-name"&gt;之前的缩进

    这些空白元素被视为&lt;ParentNode&gt;的子元素

    【讨论】:

      【解决方案2】:

      你有两个选择。您可以在解析器中设置一个选项来去除空格(禁用选项以保留空格) - 或者更好地检查您正在检查属性的节点是否实际上是一个元素,因为只有元素才能具有属性。这也更好,因为如果 XML 有这样的处理指令:&lt;?some wired stuff?&gt;,那么即使是条带化空格也无济于事,因为在处理指令中查找属性也会在这个解析器中给出 AV。所以我在这里添加了 NodeType 的代码条件:

      function GetNodeByAttributeValue(
        const AParentNode: IXMLNode;
        const AttributeName: string; AttributeValue: Variant): IXMLNode;
      var
        i: integer;
        value: Variant;
      begin
        result := nil;
        if (not Assigned(AParentNode)) or (AttributeName = '') then
          exit;
        for i := 0 to AParentNode.ChildrenCount-1 do
        begin
          result := AParentNode.Children[i];
          if result.NodeType = ntElement then
          begin
            value := Result.GetAttributeValue(AttributeName, UnAssigned);
            if not VarIsEmpty(value) and (value = AttributeValue) then
              exit;
          end;
        end;
        result := nil;
      end;
      

      您正在做的过滤也可以在 XSLT 和/或 XPath 中轻松完成,但我不知道这个解析器是否支持 XPath,也不知道 XSLT 是否真的对您有用。

      【讨论】:

        【解决方案3】:

        #text 节点是&lt;namespace:ChildNode&gt; 之前和之后的空格位。由于#text 节点只是一些文本,它们没有属性。如果您想摆脱这些节点,请尝试在 XSL 转换中使用 xsl:strip-space,或者只检查节点是否完全由空格组成。

        【讨论】:

          猜你喜欢
          • 2022-01-23
          • 2011-09-26
          • 1970-01-01
          • 2018-08-17
          • 1970-01-01
          • 1970-01-01
          • 2011-07-06
          • 2011-06-14
          • 1970-01-01
          相关资源
          最近更新 更多