我有一些简单的XML处理代码,旨在根据属性值定位传入节点的子节点:
很直观,对吧?但是在某些情况下运行时会崩溃并出现访问冲突。原因如下:
IXML* 的实现由 RemObjects SDK Library 提供。
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文档中,我也没有写任何代码来插入它们。它们为什么存在,为什么有错误,并且是否有什么方法可以防止它们破坏我的属性搜索?