我有一些简单的 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 文档中,我也没有编写任何代码来插入它们。他们为什么在那里,为什么他们有问题,我能做些什么来防止他们搞砸我的属性搜索?