XSLT有效地重新排列或重新组合节点

时间:2015-02-26 17:57:58

标签: xml xslt xpath

我正在尝试重新排列一组XML节点以进行进一步处理。 基本思想是我需要使用高效的XSLT处理来更改节点的分组。

我的输入结构是:

<all_nodes>
  <student>
    <math>
      <record>
        <detail1/>
        <detail2/>
      </record>
    </math>
    <science>
      <record>
        <detail1/>
        <detail2/>
      </record>
    </science>
    <history>
      <record>
        <detail1/>
        <detail2/>
      </record>
    </history>
  </student>
  <student>
    <math>
      <record>
        <detail1/>
        <detail2/>
      </record>
    </math>
    <science>
      <record>
        <detail1/>
        <detail2/>
      </record>
    </science>
    <history>
      <record>
        <detail1/>
        <detail2/>
      </record>
    </history>
  </student>
</all_nodes>

所需的输出按主题分组。 请注意,student节点已被删除,因为它不需要 我只需要将record节点与共同主题父节点组合在一起:

<all_nodes>
  <math>
    <record>
      <detail1/>
      <detail2/>
    </record>
    <record>
      <detail1/>
      <detail2/>
    </record>
  </math>
  <science>
    <record>
      <detail1/>
      <detail2/>
    </record>
    <record>
      <detail1/>
      <detail2/>
    </record>
  </science>
  <history>
    <record>
      <detail1/>
      <detail2/>
    </record>
    <record>
      <detail1/>
      <detail2/>
    </record>
  </history>
</all_nodes>

我能够通过使用以下代码实现所需的输出,但我认为可能有更好的方法。 你能告诉我如何改进代码吗?

<xsl:template match="/">
    <xsl:call-template name="math"/>
    <xsl:call-template name="science"/>
    <xsl:call-template name="history"/>
</xsl:template>

<xsl:template name="math">
    <xsl:element name="math">
        <xsl:apply-templates select="//math/record" />
    </xsl:element>
</xsl:template>

<xsl:template name="science">
    <xsl:element name="science">
        <xsl:apply-templates select="//science/record" />
    </xsl:element>
</xsl:template>

<xsl:template name="history">
    <xsl:element name="history">
        <xsl:apply-templates select="//history/record" />
    </xsl:element>
</xsl:template>

<xsl:template match="record">
    <xsl:copy-of select="."/>
</xsl:template>

谢谢!

2 个答案:

答案 0 :(得分:1)

如果它总是只是三个已知主题,那么你可以这么简单地做到:

[deleted]

编辑:实际上,使用密钥不太可能带来显着优势,所以为什么不让它更简单:

XSLT 1.0

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

<xsl:template match="/all_nodes">
    <xsl:copy>
        <math>
            <xsl:copy-of select="student/math/record"/>
        </math>
        <science>
            <xsl:copy-of select="student/science/record"/>
        </science>
        <history>
            <xsl:copy-of select="student/history/record"/>
        </history>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

使用 XSLT 2.0 的更通用的实现,它支持任何主题,而不在样式表中明确枚举它们:

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

    <xsl:template match="/*">
        <xsl:copy>            
            <xsl:for-each-group select="*/*/*" group-by="local-name(..)">
                <xsl:element name="{current-grouping-key()}">
                    <xsl:copy-of select="current-group()"/>
                </xsl:element>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>