我在从XML到HTML的XSL转换中匹配不同标识符时遇到问题。我有很多链接元素,如下所示:
IReliableDictionary
target属性中以#开头的每个文本都匹配一个段落元素中的xml:id属性,如下所示:
<link target="#E_1 #FCB_1 #FWH_2 #FWH_3">
我需要做的是为每个目标属性创建一个div元素,这意味着要获得以下内容:
<p xml:id="E_1">text text text</p>
<p xml:id="FCB_1">text text text</p>
<p xml:id="FWH_2">text text text</p>
<p xml:id="FWH_3">text text text</p>
我已尝试使用xsl:variable,xsl:param,xsl:key或者诸如starts-with或甚至子字符串之类的函数,但现在没有什么工作正常。所以我在寻求帮助。我仍在努力提高我的XSL技能...... 非常感谢您的帮助。 FLO
答案 0 :(得分:1)
假设使用XSLT 2.0处理器,您可以将id
函数与target
属性中的标记化值一起使用:
<xsl:template match="link[@target]">
<div class="impair">
<xsl:apply-templates select="id(for $idref in tokenize(@target, '\s+') return substring($idref, 2))" mode="wrap"/>
</div>
</xsl:template>
<xsl:template match="p" mode="wrap">
<div>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</div>
</xsl:template>
答案 1 :(得分:0)
如果您正在寻找XSLT 1.0解决方案,这里有一种可能的方法,它将target
属性转换为字符串#E_1#FCB_1#FWH_2#FWH_3#
并使用各种字符串函数来选择p
元素其中id
出现在该字符串中。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<xsl:apply-templates select="//link" />
</xsl:template>
<xsl:template match="link">
<xsl:variable name="target" select="concat(translate(@target, ' ', ''), '#')" />
<xsl:value-of select="$target" />
<div class="impair">
<xsl:apply-templates select="//p[contains($target, concat('#', @xml:id, '#'))]">
<xsl:sort select="string-length(substring-before($target, concat('#', @xml:id, '#')))" />
</xsl:apply-templates>
</div>
</xsl:template>
<xsl:template match="p">
<div>
<p><xsl:value-of select="." /></p>
</div>
</xsl:template>
</xsl:stylesheet>
如果您在target
属性中重复了ID,则此功能无效,例如#E_1 #FCB_1 #FWH_3 #FWH_3
。在这种情况下,递归调用的命名模板可以分解target
属性:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="p" match="p" use="concat('#', @xml:id)" />
<xsl:template match="/">
<xsl:apply-templates select="//link" />
</xsl:template>
<xsl:template match="link">
<div class="impair">
<xsl:call-template name="split">
<xsl:with-param name="string" select="@target" />
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="split">
<xsl:param name="string" />
<xsl:if test="$string != ''">
<xsl:apply-templates select="key('p', substring-before(concat($string, ' '), ' '))" />
<xsl:if test="contains($string, ' ')">
<xsl:call-template name="split">
<xsl:with-param name="string" select="substring-after($string, ' ')" />
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
<xsl:template match="p">
<div>
<p><xsl:value-of select="." /></p>
</div>
</xsl:template>
</xsl:stylesheet>