2012-12-14 85 views
2

我試圖解析XML如下:解析XML與內部節點

<Item status="SUCCESS" message=""> 
    <ItemDate>12/21/2012 
     <ItemType>MyType1 
     <ItemUrl title="ItemTitle">http://www.itemurl1.com</ItemUrl> 
     </ItemType> 
    </ItemDate> 
    <ItemDate>12/22/2012 
     <ItemType>MyType2 
     <ItemUrl title="Item2Title">http://www.itemurl2.com</ItemUrl> 
     </ItemType> 
    </ItemDate> 
</Item> 

正如你可以看到我不知道我們是否可以調用這個XML,但是這對我離開傳統服務。我所追求的就是解析並將其加載到對象圖中。我的對象模型如下:

public class Item 
    { 
     public string Date { get; set; } 
     public string Type { get; set; } 
     public string Url { get; set; } 
     public string Title { get; set; } 
    } 

所以,基本上,當我與解析上面的XML /串,我得到項目對象的集合來完成。你能告訴我如何用一些代碼片段來實現這個嗎?

我嘗試過使用XDocument,但由於xml的特殊結構,我無法做到這一點。

感謝, -Mike

+0

不應將屬性名稱與類名稱一起前綴,這是多餘的。 –

回答

2
XDocument xdoc = XDocument.Load(path_to_xml); 
var query = from date in xdoc.Descendants("ItemDate") 
      let type = date.Element("ItemType") 
      let url = type.Element("ItemUrl") 
      select new Item() 
      { 
       ItemDate = ((XText)date.FirstNode).Value, 
       ItemType = ((XText)type.FirstNode).Value, 
       ItemUrl = (string)url, 
       ItemTitle = (string)url.Attribute("title"), 
      }; 
+0

我覺得我們非常接近,當我運行上面的時候,我只得到一個項目,而不是項目的集合。我使用var doc = XDocument.Parse(文檔);其中文檔是xml字符串。 – Mike

+0

@Mike你可以簡單地追加'ToList();'查詢'對象來獲得一個集合。 – chridam

+0

我這樣做,仍然只有一件物品。 – Mike

1

作爲替代lazyberezovsky'sLinq2Xml投影,您也可以考慮做加載XML之前使用Xml Transform壓扁。

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="1.0" 
       > 
    <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes" /> 

    <xsl:template match="/"> 
     <Items> 
      <xsl:apply-templates select="Item/ItemDate" /> 
     </Items> 
    </xsl:template> 

    <xsl:template match="ItemDate"> 
     <Item> 
      <xsl:attribute name="ItemDate"> 
       <xsl:value-of select="normalize-space(./text()[1])" /> 
      </xsl:attribute> 
      <xsl:attribute name="ItemType"> 
       <xsl:value-of select="normalize-space(ItemType/text()[1])" /> 
      </xsl:attribute> 
      <xsl:attribute name="ItemUrl"> 
       <xsl:value-of select="normalize-space(ItemType/ItemUrl/text()[1])" /> 
      </xsl:attribute> 
      <xsl:attribute name="ItemTitle"> 
       <xsl:value-of select="normalize-space(ItemType/ItemUrl/@title)" /> 
      </xsl:attribute> 
     </Item> 
    </xsl:template> 
</xsl:stylesheet> 

這產生了下面的Xml,這很容易反序列化,例如,使用帶有XmlDocument的[XmlAttribute]attribute

<Items> 
    <Item ItemDate="12/21/2012" ItemType="MyType1" ItemUrl="http://www.itemurl1.com" ItemTitle="ItemTitle" /> 
    <Item ItemDate="12/22/2012" ItemType="MyType2" ItemUrl="http://www.itemurl2.com" ItemTitle="Item2Title" /> 
</Items> 
1

因爲您在發送的XML中只有一個節點項目,所以您只能從lazyberezovsky的代碼中獲得一個項目。這是正確的。我想你想獲得項目,但通過ItemDate節點加載它們。爲此,請使用以下經過修改的代碼:

XDocument xdoc = XDocument.Load(new StringReader(xml)); 
var query = from i in xdoc.Descendants("ItemDate") 
        let date = i 
        let type = date.Element("ItemType") 
        let url = type.Element("ItemUrl") 
        select new Item() 
          { 
           Date = ((XText) date.FirstNode).Value, 
           Type = ((XText) type.FirstNode).Value, 
           Url = (string) url, 
           Title = (string) url.Attribute("title"), 
          }; 
     var items = query.ToList();