【问题标题】:Parsing xml with inner nodes使用内部节点解析 xml
【发布时间】:2012-12-14 11:40:48
【问题描述】:

我正在尝试解析下面给出的 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/string 的解析后,我得到了一个 Item 对象的集合。您能否建议我如何使用一些代码 sn-p 来实现这一目标?

我尝试使用 XDocument,但由于 xml 的特殊结构,我无法做到。

谢谢, -迈克

【问题讨论】:

  • 你不应该在属性名前加上类名,这是多余的。

标签: c# xml linq linq-to-xml


【解决方案1】:
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"),
            };

【讨论】:

  • 我认为我们已经很接近了,当我运行上面的代码时,我只得到一个项目而不是项目集合。我使用 var doc = XDocument.Parse(documents);其中documents是xml字符串。
  • @Mike 您可以简单地将ToList(); 附加到query 对象以获取集合。
  • 我这样做了,但我仍然只得到一件。
  • @Mike 代码应该选择所有Item 节点。你真正的 xml 是什么样子的?
  • 从您发送的 xml 中只获取一项是正确的。看看你在那里有多少次节点项目。详情请看我的帖子。
【解决方案2】:

作为lazyberezovsky's Linq2Xml 投影的替代方案,您还可以考虑在加载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,它可以直接反序列化,例如将 [XmlAttribute] attribute 与 XmlDocument 一起使用。

<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>

【讨论】:

    【解决方案3】:

    因为您在发送的 xml 中只有一次节点 Item,所以您只能从lazyberezovsky 的代码中获得一个 Item。这是正确的。我想您想获取项目但通过 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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-22
      • 2018-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-02
      • 1970-01-01
      相关资源
      最近更新 更多