преобразование иерархии узлов XML - PullRequest
1 голос
/ 25 февраля 2011

Мне интересно, есть ли способ перевернуть иерархию узла, используя linq to XML или xslt.

Я хочу преобразовать

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

Где я использую существующие отношения родитель-потомок и просто переворачиваю и перестраиваю структуру, чтобы выглядеть следующим образом.

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

Ответы [ 2 ]

0 голосов
/ 01 марта 2011

Вот версия 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> 
*/
0 голосов
/ 26 февраля 2011

Мне интересно, есть ли способ перевернуть иерархию узла с помощью 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>

Объяснение : мюнхенский метод группировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...