属性値に基づいて、渡されたノードの子ノードを見つけることになっているいくつかの単純な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 *の実装は、RemObjectsSDKライブラリによって提供されます。 result.GetAttributeValue
を呼び出すuROMSXMLImpl.TROMSXMLNode.GetAttributeValue
、を呼び出すTROMSXMLNode.GetAttributeByName
、を言う
node := fNode.attributes.getNamedItem(anAttributeName);
そして、 nilfNode.attributes
を返すため、これはクラッシュします。私が理解しているように、それは決して起こらないはずです。
奇妙なことに、元の関数のforループにAParentNode.ChildrenCount
戻ると、3が返されます。しかし、元のXMLドキュメントのノードには子ノードが1つしかありません。それは私が探している基準に一致します。
<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ドキュメントに含まれておらず、挿入するコードも記述していません。なぜ彼らはそこにいるのか、そしてなぜ彼らはバグがあるのか、そして彼らが私の属性検索を台無しにするのを防ぐために私ができることはありますか?