我的小块XSL的任务是遍历XML文件中的所有OptionRef标记,并打印OptionRef标记的id和displayName属性。在“选项”部分中查找id以查找displayName。
现在,问题是: 一些OptionRef id属性使用通配符(*)作为其值的一部分。无法查找关于displayName的这些id,除非它们首先被解析为在Options部分中找到的真实id。有没有办法扩展XSL来做这种“全球化”?
我想打印与通配符匹配的所有id的id和displayNames。 例如,“A01 *”将匹配“选项”部分中的“A0101”和“A0102”,因此应打印这些ID及其显示名称。
这是XML的一个示例:
<?xml version="1.0" encoding="UTF-8"?>
<OptionList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Group>
<OptionRef id="A0102"/>
<OptionRef id="A03"/>
<OptionRef id="A04"/>
<OptionRef id="A0101"/>
<OptionRef id="A0102"/>
<OptionRef id="B01"/>
</Group>
<Options>
<Option displayName="Option A02" id="A02"/>
<Option displayName="Option A03" id="A03"/>
<Option displayName="Option A0101" id="A0101"/>
<Option displayName="Option A0102" id="A0102"/>
<Option displayName="Option A04" id="A04"/>
<Option displayName="Option B01" id="B01"/>
</Options>
<Rules>
<Opportunities>
<OptionRef id="A01*">
<OptionRef id="A03"/>
<OptionRef id="A04"/>
</OptionRef>
</Opportunities>
<Problems>
<Problem>
<OptionRef id="A03"/>
<OptionRef id="A04"/>
</Problem>
</Problems>
</Rules>
</OptionList>
这是XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" indent="yes"/>
<xsl:key name="Option_Key" match="Option" use="@id"/>
<xsl:template match="OptionRef" >
<xsl:value-of select="@id"/>:
<xsl:value-of select="key('Option_Key', @id)/@displayName"/>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:2)
如下:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="text" encoding="UTF-8"/>
<xsl:key name="Option_Key" match="Option" use="@id"/>
<xsl:variable name="options" select="/OptionList/Options/Option" />
<xsl:template match="OptionRef">
<xsl:value-of select="@id"/>
<xsl:text>: </xsl:text>
<xsl:choose>
<xsl:when test="contains(@id, '*')">
<xsl:for-each select="$options[starts-with(@id, substring-before(current()/@id, '*'))]">
<xsl:value-of select="@displayName"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="key('Option_Key', @id)/@displayName"/>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
应用于示例输入,结果将为:
A0102:
Option A0102
A03:
Option A03
A04:
Option A04
A0101:
Option A0101
A0102:
Option A0102
B01:
Option B01
A01*:
Option A0101
Option A0102
A03:
Option A03
A04:
Option A04
答案 1 :(得分:1)
假设......
*
)<OptionRef>
@id <Option>
@id长度为1-5个字符您可以使用:
<xsl:key name="Option_Key_1" match="Option" use="substring(@id, 1, 1)"/>
<xsl:key name="Option_Key_2" match="Option" use="substring(@id, 1, 2)"/>
<xsl:key name="Option_Key_3" match="Option" use="substring(@id, 1, 3)"/>
<xsl:key name="Option_Key_4" match="Option" use="substring(@id, 1, 4)"/>
<xsl:key name="Option_Key_5" match="Option" use="substring(@id, 1, 5)"/>
<xsl:template match="OptionRef">
<xsl:variable name="id" select="substring-before(concat(@id, '*'), '*')" />
<xsl:variable name="keyname" select="concat('Option_Key_', string-length($id))" />
<xsl:value-of select="concat(@id, ':
')" />
<xsl:for-each select="key($keyname, $id)">
<xsl:value-of select="@displayName" />
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
使用输入XML输出:
A0102: Option A0102 A03: Option A03 A04: Option A04 A0101: Option A0101 A0102: Option A0102 B01: Option B01 A01*: Option A0101 Option A0102 A03: Option A03 A04: Option A04 A03: Option A03 A04: Option A04
要支持长度为N
的@id值,请添加更多密钥:
<!-- ... -->
<xsl:key name="Option_Key_N" match="Option" use="substring(@id, 1, N)"/>
最后的想法:
如果您的输入文档不包含很多<OptionRef>
元素,则从键获得的运行时优势可以忽略不计。如果您关心转型绩效,请衡量替代方案。如果你没有,你根本不需要密钥,可以直接使用XPath:
<xsl:variable name="options" select="/*/Options/Option" />
<xsl:template match="OptionRef[contains(@id, '*')]">
<xsl:apply-templates select="@id" />
<xsl:apply-templates select="$options[starts-with(@id, substring-before(current()/@id, '*'))]" />
</xsl:template>
<xsl:template match="OptionRef">
<xsl:apply-templates select="@id" />
<xsl:apply-templates select="$options[@id = current()/@id]" />
</xsl:template>
<xsl:template match="OptionRef/@id">
<xsl:value-of select="concat(., ':
')" />
</xsl:template>
<xsl:template match="Option">
<xsl:value-of select="@displayName" />
<xsl:text>
</xsl:text>
</xsl:template>