2012-12-14 89 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();