如何用XSLT的for-each处理n组date与fechas映射?禁用其他模板
问题:XSLT实现任意数量date与status的一一映射
作为XSLT新手,我目前通过硬编码position()判断的方式,实现了输入XML中<date>与<status>(对应fechas属性)的一一映射,但该写法仅适配固定数量的<date>。现需适配n个<date>与fechas的场景,且禁止使用其他模板,询问是否有更优的XSLT实现方式。
输入XML
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="transformer.xsl"?> <dc> <date>11</date> <date>20</date> <status>Available</status> <status>Collected</status> </dc>
现有XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="1.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xsl:for-each select="/dc/status"> <date> <xsl:if test="position()=1"> <xsl:attribute name="fechas"> <xsl:value-of select="."/> </xsl:attribute> <xsl:for-each select="/dc/date"> <xsl:if test="position()=1"> <xsl:value-of select="."/> </xsl:if> </xsl:for-each> </xsl:if> <xsl:if test="position()=2"> <xsl:attribute name="fechas"> <xsl:value-of select="."/> </xsl:attribute> <xsl:for-each select="/dc/date"> <xsl:if test="position()=2"> <xsl:value-of select="."/> </xsl:if> </xsl:for-each> </xsl:if> </date> </xsl:for-each> </xsl:template> </xsl:stylesheet>
当前输出
<?xml version="1.0" encoding="UTF-8"?> <date fechas="Available">11</date> <date fechas="Collected">20</date>
解决方案
嘿,作为新手能写出功能代码已经很棒了!针对你要适配任意数量节点的需求,这里有个更简洁通用的实现,完全不用硬编码位置判断:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="1.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xsl:for-each select="/dc/status"> <date fechas="{.}"> <xsl:value-of select="/dc/date[position() = current()/position()]"/> </date> </xsl:for-each> </xsl:template> </xsl:stylesheet>
代码思路解释
- 利用属性值模板
{.}直接将当前<status>的内容赋值给fechas属性,比原来嵌套<xsl:attribute>的写法简洁太多。 - 通过
current()/position()获取当前遍历的<status>的序号,然后用这个序号匹配同位置的<date>节点——不管有多少个节点,只要它们的顺序一一对应,就能自动完成映射,彻底摆脱硬编码的局限。
扩展测试效果
如果输入XML新增节点:
<dc> <date>11</date> <date>20</date> <date>15</date> <status>Available</status> <status>Collected</status> <status>Processing</status> </dc>
输出会自动适配:
<?xml version="1.0" encoding="UTF-8"?> <date fechas="Available">11</date> <date fechas="Collected">20</date> <date fechas="Processing">15</date>
内容的提问来源于stack exchange,提问作者Pavel C. P.
相关产品推荐
相关产品推荐

