根据内部子节点对XML根目录进行排序

时间:2018-02-08 13:04:22

标签: c# xml xslt

我有以下XML。希望根据ChildID对其进行排序。还应根据childID

移动父节点
<?xml version="1.0" encoding="utf-8"?>
<Root>
  <Parent>
    <Children>
      <Child>
        <setting ChildID="14" />
      </Child>
      <Child>
        <setting ChildID="27" />
      </Child>
    </Children>
    <Header>
      <parentsetting name="ParentPosition" value="1" />
    </Header>
  </Parent>
  <Parent>
    <Children>
      <Child>
        <setting ChildID="11" />
      </Child>
    </Children>
    <Header>
      <parentsetting name="ParentPosition" value="0" />
    </Header>
  </Parent>
</Root>

所以最终的输出应重新排列如下。我正在使用XmlNodeList来加载XML内容。好心提醒。

    <Root>
      <Parent>
        <Children>
          <Child>
            <setting ChildID="11" />
          </Child>
        </Children>
        <Header>
          <parentsetting name="ParentPosition" value="0" />
        </Header>
      </Parent>
      <Parent>
        <Children>
          <Child>
            <setting ChildID="14" />
          </Child>
          <Child>
            <setting ChildID="27" />
          </Child>
        </Children>
        <Header>
          <parentsetting name="ParentPosition" value="1" />
        </Header>
      </Parent>
    </Root>

2 个答案:

答案 0 :(得分:0)

您可以从拥有身份模板开始,该模板将复制所有节点:

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

然后,如果要对Parent个节点进行排序,请首先在其父元素Root处进行模板匹配。在应用模板时进行排序。如:

<xsl:template match="Root">
    <xsl:copy>
        <xsl:apply-templates>
            <!-- Select the target node to be sorted.
              This time, we select the first descendant node with
              an attribute ChildID -->
            <xsl:sort select="descendant::*/@ChildID[1]" order="ascending"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

就是这样。整个样式表如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Root">
        <xsl:copy>
            <xsl:apply-templates>
                <xsl:sort select="descendant::*/@ChildID" order="ascending"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

一旦问题是由属性排序的数字SO,你需要强制它,否则它会在像ChildID="111" and ChildID="21"这样的东西上失败,如果使用alpha排序,它会对第一个先前排序。

你还有2个空格缩进。大多数XML都不需要缩进,但是你可以在那里使用缩进。如果没有缩进,它会更快(微优化)和更小,但是你提供了输出示例。某些处理器会进行缩进,但默认情况下可能不会为2,因此我们会以处理成本更精确地使用它。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
    <!-- two space indent -->
    <xsl:param name="indent-increment" select="'  '" />
    <xsl:strip-space elements="*"/>
    <!-- no XML declaration -->
    <xsl:output omit-xml-declaration="yes" method="xml"/>
    <!-- copy the root -->
    <xsl:template match="Root">
        <xsl:copy>
            <xsl:apply-templates>
                <!-- force number type for attribute sort -->
                <xsl:sort select="descendant::*/@ChildID" order="ascending" data-type="number"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <!-- more stuff for the indent -->
    <xsl:template match="*">
        <xsl:param name="indent" select="'&#xA;'"/>

        <xsl:value-of select="$indent"/>
        <xsl:copy>
            <xsl:copy-of select="@*" />
            <xsl:apply-templates>
                <xsl:with-param name="indent"
                select="concat($indent, $indent-increment)"/>
            </xsl:apply-templates>
            <xsl:if test="*">
                <xsl:value-of select="$indent"/>
            </xsl:if>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

使用

进行测试
<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Parent>
        <Children>
            <Child>
                <setting ChildID="14" />
            </Child>
            <Child>
                <setting ChildID="27" />
            </Child>
        </Children>
        <Header>
            <parentsetting name="ParentPosition" value="1" />
        </Header>
    </Parent>
    <Parent>
        <Children>
            <Child>
                <setting ChildID="111" />
            </Child>
        </Children>
        <Header>
            <parentsetting name="ParentPosition" value="3" />
        </Header>
    </Parent>
    <Parent>
        <Children>
            <Child>
                <setting ChildID="12" />
            </Child>
        </Children>
        <Header>
            <parentsetting name="ParentPosition" value="0" />
        </Header>
    </Parent>
    <Parent>
        <Children>
            <Child>
                <setting ChildID="11" />
            </Child>
        </Children>
        <Header>
            <parentsetting name="ParentPosition" value="0" />
        </Header>
    </Parent>
</Root>

制作了这个:

<Root>
<Parent>
  <Children>
    <Child>
      <setting ChildID="11"/>
    </Child>
  </Children>
  <Header>
    <parentsetting name="ParentPosition" value="0"/>
  </Header>
</Parent>
<Parent>
  <Children>
    <Child>
      <setting ChildID="12"/>
    </Child>
  </Children>
  <Header>
    <parentsetting name="ParentPosition" value="0"/>
  </Header>
</Parent>
<Parent>
  <Children>
    <Child>
      <setting ChildID="14"/>
    </Child>
    <Child>
      <setting ChildID="27"/>
    </Child>
  </Children>
  <Header>
    <parentsetting name="ParentPosition" value="1"/>
  </Header>
</Parent>
<Parent>
  <Children>
    <Child>
      <setting ChildID="111"/>
    </Child>
  </Children>
  <Header>
    <parentsetting name="ParentPosition" value="3"/>
  </Header>
</Parent></Root>