xml节点层次结构转换

时间:2011-02-25 20:03:47

标签: xml linq xslt

我想知道是否有办法使用linq转换节点的层次结构到XML或xslt。

我想转型

<hardware>
    <software/>
    <software/>
</hardware>
<hardware>
    <software/>
    <software/>
</hardware>

我使用现有的父子关系,只需翻转并重建结构,就像这样。

<software>
    <hardware/>
    <hardware/>
</software>
<software>
    <hardware/>
    <hardware/>
</software>

2 个答案:

答案 0 :(得分:0)

  

我想知道是否有办法   使用linq翻转节点的层次结构   到XML或xslt。

     

。 。 。 。 。 。 。

     

我使用现有父母的地方 -   孩子的关系,只是翻转和   重建结构。

是。这种转变:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kSoftByName" match="software"
  use="@name"/>

 <xsl:template match=
  "software[generate-id()
           =
            generate-id(key('kSoftByName',@name)[1])
           ]
  ">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates mode="copy"
      select="key('kSoftByName',@name)/.."/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="hardware" mode="copy">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

应用于此XML文档时:

<inventory>
    <hardware name="PC">
        <software name="Office"/>
        <software name="Safari"/>
        <software name="Windows"/>
    </hardware>
    <hardware name="Mac">
        <software name="Safari"/>
        <software name="Office"/>
        <software name="Leopard"/>
    </hardware>
</inventory>

会产生想要的正确结果:

<software name="Office">
   <hardware name="PC"/>
   <hardware name="Mac"/>
</software>
<software name="Safari">
   <hardware name="PC"/>
   <hardware name="Mac"/>
</software>
<software name="Windows">
   <hardware name="PC"/>
</software>
<software name="Leopard">
   <hardware name="Mac"/>
</software>

解释:Muenchian分组方法。

答案 1 :(得分:0)

这是LINQ版本。

给出像这样的xml:

var xml = @"
<inventory>
    <hardware name=""PC"">
        <software name=""Office""/>
        <software name=""Safari""/>
        <software name=""Windows""/>
    </hardware>
    <hardware name=""Mac"">
        <software name=""Safari""/>
        <software name=""Office""/>
        <software name=""Leopard""/>
    </hardware>
</inventory>";

以下是将其拆分的查询:

var xd = XDocument.Parse(xml);

var query =
    from h in xd.Root.Elements()
    from s in h.Elements()
    select new
    {
        hardware = h.Attribute("name").Value,
        software = s.Attribute("name").Value
    };

var lookup = query.ToLookup(q => q.software, q => q.hardware);

这是将它重新组合在一起的查询,按需要翻转:

var result =
    new XDocument
    (
        new XElement
        (
            "inventory",
            from s in query.Select(q => q.software).Distinct()
            select new XElement
            (
                "software",
                new XAttribute("name", s),
                from h in lookup[s].Distinct()
                select new XElement
                (
                    "hardware",
                    new XAttribute("name", h)
                )
            )
        )
    );

/*
<inventory>
  <software name="Office">
    <hardware name="PC" />
    <hardware name="Mac" />
  </software>
  <software name="Safari">
    <hardware name="PC" />
    <hardware name="Mac" />
  </software>
  <software name="Windows">
    <hardware name="PC" />
  </software>
  <software name="Leopard">
    <hardware name="Mac" />
  </software>
</inventory> 
*/