我有一个包含集合定义和元素定义的xml文档。示例XML:
<!-- a set definition -->
<a name="SET.1" mnemonic="NAME_SET" ... />
<!-- an element definition -->
<a name="NAME_SET.1" mnemonic="Element1" .../>
我无法控制进入的xml。判断集合定义和元素定义之间区别的唯一方法是name
属性的值。在集合定义中,它将以“SET”开头;在元素定义中,它将以set的助记符属性的值开始。
我想使用XSLT按集合排序文件,然后按集合中的元素排序。含义:
<!-- a set definition -->
<a name="SET.1" mnemonic="ANIMAL_SET" ... />
<!-- an element definition -->
<a name="ANIMAL_SET.1" mnemonic="Mouse" .../>
... all the elements in ANIMAL_SET
<!-- a set definition -->
<a name="SET.2" mnemonic="VEHICLE_SET" ... />
<!-- an element definition -->
<a name="VEHICLE_SET.1" mnemonic="Car" .../>
... all the elements in VEHICLE_SET
我相信要这样做,我会使用<xsl:for-each>
,但我不确定如何。有什么想法吗?
编辑以更清楚地解释我的样本xml:
原始xml:
<ExternalTag attribute="00061000">
<TagOnSameLevel attribute="foo"/>
<a attribute="1" mnemonic="CAR_SET" name="SET.102" />
<a attribute="3" mnemonic="Toyota" name="CAR_SET.3" />
<a attribute="11" mnemonic="lion" name="ANIMAL_SET.12" />
<a attribute="2" mnemonic="Chevy" name="CAR_SET.2" />
<a attribute="2" mnemonic="ANIMAL_SET" name="SET.1034" />
<a attribute="6" mnemonic="tiger" name="ANIMAL_SET.6" />
</ExternalTag>
xslt后的所需xml:按名称排序的SET,每组中的元素也按名称排序。
<ExternalTag attribute="00061000">
<TagOnSameLevel attribute="foo"/>
<a attribute="1" mnemonic="CAR_SET" name="SET.102" />
<a attribute="2" mnemonic="Chevy" name="CAR_SET.2" />
<a attribute="3" mnemonic="Toyota" name="CAR_SET.3" />
<a attribute="2" mnemonic="ANIMAL_SET" name="SET.1034" />
<a attribute="11" mnemonic="lion" name="ANIMAL_SET.12" />
<a attribute="6" mnemonic="tiger" name="ANIMAL_SET.6" />
</ExternalTag>
答案 0 :(得分:2)
这是你可以做到的一种方式:
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:template match="/">
<output>
<xsl:for-each select="input/a[starts-with(@name, 'SET.')]">
<xsl:copy-of select="."/>
<xsl:for-each select="../a[starts-with(@name, current()/@mnemonic)]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
鉴于格式良好的测试输入:
<input>
<a name="SET.1" mnemonic="ANIMAL_SET"/>
<a name="SET.2" mnemonic="VEHICLE_SET"/>
<a name="ANIMAL_SET.1" mnemonic="Mouse" />
<a name="VEHICLE_SET.1" mnemonic="Car"/>
<a name="ANIMAL_SET.1" mnemonic="Cat" />
<a name="VEHICLE_SET.1" mnemonic="Truck"/>
</input>
结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<a name="SET.1" mnemonic="ANIMAL_SET"/>
<a name="ANIMAL_SET.1" mnemonic="Mouse"/>
<a name="ANIMAL_SET.1" mnemonic="Cat"/>
<a name="SET.2" mnemonic="VEHICLE_SET"/>
<a name="VEHICLE_SET.1" mnemonic="Car"/>
<a name="VEHICLE_SET.1" mnemonic="Truck"/>
</output>
更智能的输出形式会将每个组包装在组合元素中。
鉴于您的更新输入,请尝试这种方式:
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="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ExternalTag">
<xsl:copy>
<xsl:apply-templates select="@* | *[not(self::a)] | a[starts-with(@name, 'SET.')]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:copy-of select="."/>
<xsl:for-each select="../a[starts-with(@name, current()/@mnemonic)]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>