这些名为“#text”的XML节点是什么意思?

4
我有一些简单的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 Library 提供。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文档中,我也没有写任何代码来插入它们。它们为什么存在,为什么有错误,并且是否有什么方法可以防止它们破坏我的属性搜索?

3个回答

8

文本节点是解析器返回的空格。


<namespace:ChildNode name="right-name">之前的缩进。

这些空格元素被视为<ParentNode>的子元素。


2

您有两个选择。您可以在解析器中设置一个选项以去除空格(禁用选项以保留空格)-或者更好的是,您可以检查您正在检查属性的节点是否实际上是一个元素,因为只有元素才能具有属性。这也更好,因为如果XML具有处理指令,例如:<?some wired stuff?>,即使去除空格也无济于事,因为在此解析器中,在处理指令中查找属性也会导致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对你是否真正有用。


1

#text节点是<namespace:ChildNode>之前和之后的空格位。由于#text节点只是文本片段,它们没有属性。如果你想要去掉这些节点,可以尝试在XSL转换中使用xsl:strip-space,或者检查节点是否完全由空格组成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接