如何匹配标识符?

时间:2016-05-22 14:15:25

标签: xml xslt

我在从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或者诸如s​​tarts-with或甚至子字符串之类的函数,但现在没有什么工作正常。所以我在寻求帮助。我仍在努力提高我的XSL技能...... 非常感谢您的帮助。 FLO

2 个答案:

答案 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>