2010-07-21 29 views
3

我有一個本應定位基於屬性值的節點在傳送一個子節點一些簡單的處理XML代碼:這些名爲「#text」的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回報。據我瞭解,這不應該發生。

奇怪的是,回到原始函數中的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文檔中,我沒有編寫任何代碼來插入它們。他們爲什麼在那裏,爲什麼他們是越野車,有什麼我可以做的,以防止他們搞砸我的屬性搜索?

回答

7

文本節點是解析器返回的空白。
即壓痕<namespace:ChildNode name="right-name">

這些空白元素之前被視爲<ParentNode>

1

#text節點是<namespace:ChildNode>之前和之後的空白位。由於#text節點只是文本的一部分,所以它們沒有屬性。如果您想擺脫這些節點,請嘗試在XSL轉換中使用xsl:strip-space,或者只檢查節點是否完全由空白組成。

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對你來說真的很方便。