【问题标题】:Sorting an XML file through XSL通过 XSL 对 XML 文件进行排序
【发布时间】:2010-05-26 04:26:01
【问题描述】:

我有一个想要按属性排序的 XML 文件。文件结构如下图:

<wb xmlns:cf="http://www.macromedia.com/2004/cfform">

    <a:form name="chart">  

        <a:input FIELDNUMBER="09" INDEX="2" LEFT="200" />
        <a:input FIELDNUMBER="08" INDEX="3" LEFT="200" />

        <a:fieldset FIELD="a" FIELDNAME="FieldSet1">                              
            <a:input FIELDNUMBER="02" INDEX="4" LEFT="200" />
            <a:select1  FIELDNUMBER="01" />
        </a:fieldset>

        <a:fieldset FIELD="b" FIELDNAME="FieldSet1">                              
            <a:input FIELDNUMBER="04" INDEX="7" LEFT="200" />
            <a:select1  FIELDNUMBER="03" />
            <a:fieldset FIELD="c" FIELDNAME="FieldSet1">                              
                <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
                <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
            </a:fieldset>
       </a:fieldset>

    </a:form>

</wb> 

我想通过@fieldnumber 对上述XML 进行排序,但同时我想保持XML 的相同结构。我已经设法对其他 XML 文件进行排序,但它们没有这样的嵌套级别。单独使用 XSL 是否可行,如果可以,如何实现?

输出应该如下:

<wb xmlns:cf="http://www.macromedia.com/2004/cfform">

    <a:form name="chart">  

        <a:input FIELDNUMBER="08" INDEX="3" LEFT="200" />
        <a:input FIELDNUMBER="09" INDEX="2" LEFT="200" />

        <a:fieldset FIELD="a" FIELDNAME="FieldSet1">                              
            <a:select1  FIELDNUMBER="01" />
            <a:input FIELDNUMBER="02" INDEX="4" LEFT="200" />
        </a:fieldset>

        <a:fieldset FIELD="b" FIELDNAME="FieldSet1">                              
            <a:select1  FIELDNUMBER="03" />
            <a:input FIELDNUMBER="04" INDEX="7" LEFT="200" />
            <a:fieldset FIELD="c" FIELDNAME="FieldSet1">                              
                <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
                <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
            </a:fieldset>
       </a:fieldset>

    </a:form>

</wb> 

再举一个例子,如果 FIELDNUMBER 04 更改为大于 7 的值,例如 10(在本例中假设为 10),则 FIELD 值为 b 的字段集的输出变为:

        <a:fieldset FIELD="b" FIELDNAME="FieldSet1">                              
            <a:select1  FIELDNUMBER="03" />
            <a:fieldset FIELD="c" FIELDNAME="FieldSet1">                              
                <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
                <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
            </a:fieldset>
            <a:input FIELDNUMBER="10" INDEX="7" LEFT="200" />
       </a:fieldset>

【问题讨论】:

  • 在这种情况下,您不清楚“保持 XML 的相同结构”是什么意思。显示对样本输入进行排序后的输出是什么样的。
  • 完成。 Jim,基本上我的意思是,如果 XML 包含大约 20 行,那么排序后的输出将具有相同数量的行。这意味着排序函数将根据字段编号简单地转置行,但同时保留相同的嵌套和等量的级别。使排序有点困难的是在 a:fieldset 中有/可能有嵌套元素,我也想按 fieldnumber 对其进行排序。
  • 信息还不够。如果将字段编号 04 更改为 FIELDNUMBER="10",它会保留在原处还是排序在包含 05 和 06 的字段集后面?
  • 好问题!它必须在元素 06 之后!因此,将 FIELDNUMBER 04 更改为 10 的输出底部变为:
    a:fieldset>
  • 好的,这和08和09在01和02之前的排序不一致。

标签: xml xslt


【解决方案1】:

尽管 Jim Garrison 指出了不一致的地方,但我试图提出与您的描述相符的内容:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:for-each select="*">
        <xsl:sort select="@FIELDNUMBER|.//@FIELDNUMBER"/>
        <xsl:apply-templates select="." />
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

排序首先对元素的 FIELDNUMBER 属性起作用,或者如果元素本身没有FIELDNUMBER 属性,则对它在元素的子元素上找到的第一个FIELDNUMBER 属性进行排序。这是输出(xmlns:a 被添加到源文档中,所以它被带到了输出):

<?xml version="1.0" encoding="utf-8"?>
<wb xmlns:cf="http://www.macromedia.com/2004/cfform" xmlns:a="urn:dummy">
  <a:form name="chart">
    <a:fieldset FIELD="a" FIELDNAME="FieldSet1">
      <a:select1 FIELDNUMBER="01" />
      <a:input FIELDNUMBER="02" INDEX="4" LEFT="200" />
    </a:fieldset>
    <a:fieldset FIELD="b" FIELDNAME="FieldSet1">
      <a:select1 FIELDNUMBER="03" />
      <a:input FIELDNUMBER="04" INDEX="7" LEFT="200" />
      <a:fieldset FIELD="c" FIELDNAME="FieldSet1">
        <a:input FIELDNUMBER="05" INDEX="6" LEFT="200" />
        <a:input FIELDNUMBER="06" INDEX="8" LEFT="200" />
      </a:fieldset>
    </a:fieldset>
    <a:input FIELDNUMBER="08" INDEX="3" LEFT="200" />
    <a:input FIELDNUMBER="09" INDEX="2" LEFT="200" />
  </a:form>
</wb>

【讨论】:

  • 弗朗西斯,太棒了!您不仅设法理解了我的查询,而且还设法给了我一个完全符合我预期的输出!
猜你喜欢
  • 2012-03-18
  • 1970-01-01
  • 1970-01-01
  • 2015-06-05
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多