2013-05-02 79 views
2

我有一個Xml文件,我想在XPath中進行過濾。我嘗試了很多例子,但沒有一個能夠幫助我毫無疑問地犯了一些錯誤。 我是XPath新手,請幫我找到解決方案。如何爲XML創建XPath?

<PeopleBatch Counter="3"> 
<Citriz ID="1d9a88fe-f9cc-4add-b6d1-01e41c561bfb" mVersion="1.0.0" mSequence="1" pVersion="0.0.1" xmlns="http://Citriz/Schemas"> 
    <People Action="U" Status="CD" PeopleID="1" PeopleShortName="Billy" PeopleLongName="Billy Smith" PeopleTypeCode="Commercial" CountryCode="USA" PeopleStatus="Current"> 
      <PeopleRole Action="U" Status="CD" ID="1" CustomerRoleShortName="Billy" CustomerRoleLongName="Billy Smith" TypeCode="OUTS"> 
        <SendRole RoleType="N" ActiveRole="Y"/> 
      </PeopleRole> 
    </People> 
</Citriz> 
<Citriz ID="1d9a88fe-f9cc-4add-b6d1-01e41c561bfc" mVersion="1.0.0" mSequence="2" pVersion="0.0.1" xmlns="http://Citriz/Schemas"> 
    <People Action="U" Status="CD" PeopleID="2" PeopleShortName="Carl" PeopleLongName="Carl Thomas" PeopleTypeCode="Commercial" CountryCode="USA" PeopleStatus="Current"> 
      <PeopleRole Action="U" Status="CD" ID="2" CustomerRoleShortName="Carl" CustomerRoleLongName="Carl Thomas" TypeCode="INSS"> 
        <SendRole RoleType="N" ActiveRole="Y"/> 
      </PeopleRole> 
    </People> 
</Citriz> 
<Citriz ID="1d9a88fe-f9cc-4add-b6d1-01e41c561bfd" mVersion="1.0.0" mSequence="3" pVersion="0.0.1" xmlns="http://Citriz/Schemas"> 
    <People Action="U" Status="CD" PeopleID="3" PeopleShortName="Ryan" PeopleLongName="Ryan Black" PeopleTypeCode="Commercial" CountryCode="USA" PeopleStatus="Current"> 
      <PeopleRole Action="U" Status="CD" ID="3" CustomerRoleShortName="Ryan" CustomerRoleLongName="Ryan Black" TypeCode="INSS"> 
        <SendRole RoleType="N" ActiveRole="Y"/> 
      </PeopleRole> 
    </People> 
</Citriz> 

我需要哪些子節點屬性包含類型碼= 「INSS」 這個值的所有那些 「Citriz」 節點。或者建議我是否有其他好方法。

回答

1

我想你的<Citriz>節點與Xml名稱空間有問題

XNamespace ns = "http://Citriz/Schemas"; 
var peopleRole = XDocument.Parse(xml) 
        .Descendants(ns + "PeopleRole") 
        .Where(p => p.Attribute("TypeCode").Value == "INSS") 
        .ToList(); 
+0

非常感謝答覆,但它不返回兩個節點。 – 2013-05-02 21:07:44

+0

@PankajMishra我假設你想要第一個。只需用'Where'代替'First'。就這些。我更新了答案。 – I4V 2013-05-02 21:09:05

6

鑑於您使用的是LINQ to XML,我不會使用XPath開始。我會用:

XNamespace ns = "http://Citriz/Schemas"; 
var nodes = doc.Descendants(ns + "Citriz") 
       .Where(x => x.Descendants() 
          .Any(y => (string) x.Attribute("TypeCode") == "INSS")); 

或者,如果它要總是PeopleRole元素中PeopleCitriz(在每個級別只是一個單一的元素):

XNamespace ns = "http://Citriz/Schemas"; 
var nodes = doc.Descendants(ns + "Citriz") 
       .Where(x => (string) x.Element(ns + "People") 
            .Element(ns + "PeopleRole") 
            .Attribute("TypeCode") == "INSS")); 

我敢肯定這個可以可以在XPath中明智地完成,但我個人認爲LINQ to XML更簡單,就分離與「代碼」部分分離的數據部分(元素名稱,期望值等)而言(「我正在尋找後代「或」我正在尋找職業bute值「)。

+0

非常感謝您的回答。 兩種方式都不返回任何值。毫無疑問,我正在做任何錯誤或失去一些東西。我需要額外的東西嗎? – 2013-05-02 20:56:45

+0

@PankajMishra:此代碼由於命名空間而失敗 - 我沒有發現命名空間。我已經適當地修復了代碼。 – 2013-05-02 21:17:35

0

您可以認爲XPath等同於在文件系統中導航目錄樹。將額外的「目錄」添加到xpath查詢會讓您更深入DOM樹。

//PeopleRole[@TypeCode="inss"]/../.. 

會發現型PeopleRole的所有節點,用的TypeCode屬性等於「INSS」,然後向上移動到水平樹,返回包含匹配PeopleRoles

+0

如果要評估XNode中的XPath表達式,可以使用'XPathSelectElements'擴展方法。請參閱http://msdn.microsoft.com/en-us/library/bb387057.aspx – flup 2013-05-02 20:04:03