Xslt 重新排序从xsl返回的节点:choose
使用xsl:choose(XSLT 1.0)重新排列所选节点组的有效方法是什么 以下是示例源XML:Xslt 重新排序从xsl返回的节点:choose,xslt,xslt-1.0,remap,xsl-choose,Xslt,Xslt 1.0,Remap,Xsl Choose,使用xsl:choose(XSLT 1.0)重新排列所选节点组的有效方法是什么 以下是示例源XML: <Universe> <CObj> <Galaxies> <Galaxy> <Profile> <Name>MilkyWay</Name> <Age>12.5</Age>
<Universe>
<CObj>
<Galaxies>
<Galaxy>
<Profile>
<Name>MilkyWay</Name>
<Age>12.5</Age>
</Profile>
<PlanetarySystem>
<Name>Solar</Name>
<Location></Location>
<Planet>
<Name>Earth</Name>
<Satellite>Y</Satellite>
...
...
...
</Planet>
...
...
...
</PlanetarySystem>
<PlanetarySystem>
...
...
...
</PlanetarySystem>
</Galaxy>
<Galaxy>
...
...
...
</Galaxy>
</Galaxies>
</CObj>
</Universe>
银河系
12.5
太阳的
土
Y
...
...
...
...
...
...
...
...
...
...
...
...
XSL代码段:
<xsl:template name="get-galaxy-types">
<xsl:variable name="galaxy_age1" select ="1" />
<xsl:variable name="galaxy_age2" select ="5" />
<xsl:variable name="galaxy_age3" select ="10" />
<xsl:for-each select="Galaxies/Galaxy/Profile/Age">
<xsl:choose>
<xsl:when test=".=$galaxy_age2">
<GalaxyType2>
<xsl:value-of select="../Profile/Name"/>
</GalaxyType2>
</xsl:when>
<xsl:when test=".=$galaxy_age3">
<GalaxyType3>
<xsl:value-of select="../Profile/Name"/>
</GalaxyType3>
</xsl:when>
<xsl:when test=".=$galaxy_age1">
<GalaxyType1>
<xsl:value-of select="../Profile/Name"/>
</GalaxyType1>
</xsl:when>
</xsl:choose>
</xsl:for-each>
从主模板调用上述XSL模板,如:
<xsl:template match="Universe">
<GalaxyTypes>
<xsl:call-template name="get-galaxy-types"/>
</GalaxyTypes>
</xsl:template>
输出XML:
请注意,
的顺序不能更改
<Universe>
...
...
...
<GalaxyTypes>
<GalaxyType2>xxxxxx</GalaxyType2>
<GalaxyType3>xxxxxx</GalaxyType3>
<GalaxyType1>xxxxxx</GalaxyType1>
</GalaxyTypes>
...
...
...
</Universe>
...
...
...
xxxxxx
xxxxxx
xxxxxx
...
...
...
由于xsl:choose
在找到匹配项时返回XML节点,因此我无法找到一种直接的方法来控制GalaxyType
在输出XML中的显示顺序
我如何拥有一个通用模板来对将来可能添加的、可能符合类似要求的任何元素执行重新排序。我可以在这个XSL中使用一个重新映射模板,但我不确定如何以一种非常优雅和高效的方式实现这一点。在分散的代码片段之间导航非常困难。不过,在我看来,你应该改变你的战略,比如:
<xsl:template match="?">
...
<GalaxyTypes>
<xsl:apply-templates select="??/???/Galaxy">
<xsl:sort select="Profile/Age" data-type="number" order="ascending"/>
</xsl:apply-templates=>
</GalaxyTypes>
...
</xsl:template>
<xsl:template match="Galaxy">
<xsl:choose>
<xsl:when test="Profile/Age=$galaxy_age1">
<GalaxyType1>
<xsl:value-of select="Profile/Name"/>
</GalaxyType1>
</xsl:when>
<xsl:when test="Profile/Age=$galaxy_age2">
<GalaxyType2>
<xsl:value-of select="Profile/Name"/>
</GalaxyType2>
</xsl:when>
<xsl:when test="Profile/Age=$galaxy_age3">
<GalaxyType3>
<xsl:value-of select="Profile/Name"/>
</GalaxyType3>
</xsl:when>
</xsl:choose>
</xsl:template>
...
...
--请注意,如果所有星系都是一个统一的
元素,并使用类型属性来区分它们,则输出的格式会更好。我猜您希望首先放置匹配星系-age1的星系,然后放置匹配星系-age2的星系,最后是galaxy-age3的版本。我还假设指定的年龄可能不是按升序排列的(也就是说,galaxy-age3可能小于galaxy-age1)
首先,对Galaxy元素执行xsl:for-each可能更自然
<xsl:for-each select="Galaxies/Galaxy">
但这并不是很优雅。最好是简单地使用一个匹配Galaxy的模板,并使用三个单独的xsl:apply templates来选择Galaxy;每个年龄一个
也试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:param name="galaxy_age1" select="1" />
<xsl:param name="galaxy_age2" select="5" />
<xsl:param name="galaxy_age3" select="10" />
<xsl:template match="Universe">
<GalaxyTypes>
<xsl:apply-templates select="Galaxies/Galaxy[Profile/Age = $galaxy_age1]">
<xsl:with-param name="num" select="1" />
</xsl:apply-templates>
<xsl:apply-templates select="Galaxies/Galaxy[Profile/Age = $galaxy_age2]">
<xsl:with-param name="num" select="2" />
</xsl:apply-templates>
<xsl:apply-templates select="Galaxies/Galaxy[Profile/Age = $galaxy_age3]">
<xsl:with-param name="num" select="3" />
</xsl:apply-templates>
</GalaxyTypes>
</xsl:template>
<xsl:template match="Galaxy">
<xsl:param name="num" />
<xsl:element name="Galaxy{$num}">
<xsl:value-of select="Profile/Name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:param name="galaxy_age1" select="1" />
<xsl:param name="galaxy_age2" select="10" />
<xsl:param name="galaxy_age3" select="5" />
<xsl:key name="galaxy" match="Galaxy" use="Profile/Age" />
<xsl:template match="Universe">
<GalaxyTypes>
<xsl:apply-templates select="key('galaxy', $galaxy_age1)">
<xsl:with-param name="num" select="1" />
</xsl:apply-templates>
<xsl:apply-templates select="key('galaxy', $galaxy_age2)">
<xsl:with-param name="num" select="2" />
</xsl:apply-templates>
<xsl:apply-templates select="key('galaxy', $galaxy_age3)">
<xsl:with-param name="num" select="3" />
</xsl:apply-templates>
</GalaxyTypes>
</xsl:template>
<xsl:template match="Galaxy">
<xsl:param name="num" />
<xsl:element name="Galaxy{$num}">
<xsl:value-of select="Profile/Name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<> > > >编辑:,为了使这更有效,请考虑使用一个关键字来查找<强> Galaxy>元素。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:param name="galaxy_age1" select="1" />
<xsl:param name="galaxy_age2" select="5" />
<xsl:param name="galaxy_age3" select="10" />
<xsl:template match="Universe">
<GalaxyTypes>
<xsl:apply-templates select="Galaxies/Galaxy[Profile/Age = $galaxy_age1]">
<xsl:with-param name="num" select="1" />
</xsl:apply-templates>
<xsl:apply-templates select="Galaxies/Galaxy[Profile/Age = $galaxy_age2]">
<xsl:with-param name="num" select="2" />
</xsl:apply-templates>
<xsl:apply-templates select="Galaxies/Galaxy[Profile/Age = $galaxy_age3]">
<xsl:with-param name="num" select="3" />
</xsl:apply-templates>
</GalaxyTypes>
</xsl:template>
<xsl:template match="Galaxy">
<xsl:param name="num" />
<xsl:element name="Galaxy{$num}">
<xsl:value-of select="Profile/Name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:param name="galaxy_age1" select="1" />
<xsl:param name="galaxy_age2" select="10" />
<xsl:param name="galaxy_age3" select="5" />
<xsl:key name="galaxy" match="Galaxy" use="Profile/Age" />
<xsl:template match="Universe">
<GalaxyTypes>
<xsl:apply-templates select="key('galaxy', $galaxy_age1)">
<xsl:with-param name="num" select="1" />
</xsl:apply-templates>
<xsl:apply-templates select="key('galaxy', $galaxy_age2)">
<xsl:with-param name="num" select="2" />
</xsl:apply-templates>
<xsl:apply-templates select="key('galaxy', $galaxy_age3)">
<xsl:with-param name="num" select="3" />
</xsl:apply-templates>
</GalaxyTypes>
</xsl:template>
<xsl:template match="Galaxy">
<xsl:param name="num" />
<xsl:element name="Galaxy{$num}">
<xsl:value-of select="Profile/Name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这个顺序是不是会以升序的方式GalaxyType
呢?最终输出的顺序需要与上面提到的不同,并且可能会根据用户的需求而变化。这就是我考虑是否可以从调用的模板获取galaxy Type
重新映射XML节点的原因。此外,我无法更改源/输出XML。@Thinkster我的印象是年龄类型取决于年龄并按顺序排列。如果不是这样,您需要澄清这些类型是如何传递到样式表的。它们是否总是正好有三个(从您的硬编码中可以看出)是的,GalaxyTypes与年龄有关,但根据消费者的需要按自定义顺序进行排序。年龄值在xsl:variable
中传递(有更新的问题)。这些变量是为测试而硬编码的,但这是在调用XSL编译器时从代码中设置的。计数不会动态更改,并且在设置后将保持不变。我仍然感到困惑:是什么决定了顺序?是不是在样式表中显示的变量的顺序?您的示例在这方面是矛盾的。--我也不是确定您认为如何“在调用XSL编译器时从代码中”传递变量。我相信您需要使用参数来实现这一点?是的,这些是作为参数传递的。我开始研究它,假设XSL:choose
将保持返回节点的顺序,因此我按照该顺序进行了XSL:when
比较(sry这不是我最初想要的顺序,我只是修改了XSL片段)。由于这不起作用,因为从xsl:choose
返回的节点集顺序取决于首先匹配的内容,因此我正在寻找一种方法来定义自定义顺序,其中从xsl:choose
重新运行的节点集将被重新排序。是的,这会起作用,但这会比xsl:choose
更有效吗?因为如果我没有错,这将迭代多少次,最多3次(或更多,取决于计数),在使用xsl:choose
时,我们可以通过一次运行匹配所有内容?这就是我认为如果我可以运行一次并重新映射返回的节点集的原因