Xml XSLT可以有效地重新排列或重组节点
我正在尝试重新排列一组XML节点以进行进一步处理。 基本思想是,我需要使用高效的XSLT处理更改节点的分组 我的输入结构是:Xml XSLT可以有效地重新排列或重组节点,xml,xslt,xpath,Xml,Xslt,Xpath,我正在尝试重新排列一组XML节点以进行进一步处理。 基本思想是,我需要使用高效的XSLT处理更改节点的分组 我的输入结构是: <all_nodes> <student> <math> <record> <detail1/> <detail2/> </record> </math> <science>
<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>
通过使用以下代码,我能够实现所需的输出,但是我认为可能有更好的方法。
你能建议我如何改进代码吗
<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>
谢谢大家! 如果它总是只有三个已知的主题,那么你可以很简单地这样做:
[deleted]
编辑:实际上,使用密钥不太可能带来显著的优势,所以为什么不让它变得更简单:
XSLT1.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>
一个更通用的实现,使用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>
您使用的是哪个版本的XSLT?第一条注释-当名称固定时,您不需要使用
,只需使用文本
。“数学、科学和历史”是一个详尽的列表吗?我使用的是XSLT 2.0版。目前的假设是,我可能有一个不确定数量的主题。现在有几个主题,但我需要出于安全考虑,假设将来可能会添加或删除一些主题——这也是我当前代码中的缺陷。那么,Mads Hansen为您提供了XSLT 2.0的答案,您将在这里找到XSLT1.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>