在 XSLT 中组合空格分隔的属性



我正在处理的转换合并了两个具有空格分隔属性的模板。

一个例子是:

<document template_id="1">
  <header class="class1 class2" />
</document>
<document template_id="2">
  <header class="class3 class4" />
</document>

转换后,我希望它是这样的:

<document>
  <header class="class1 class2 class3 class4" />
</document>

如何实现这一点?

我试过(凭记忆写(:

<xsl:template match="/">
  <header>
    <xsl:attribute name="class">
      <xsl:for-each select=".//header">
        <xsl:value-of select="@class"/>
      </xsl:for-each>
    </xsl:attribute>
  </header>
</xsl:template>

但这将它们全部附加在一起,但我需要将它们分开......如果也是独一无二的,那就太棒了。

谢谢

试试这个模板,它只是在所有标题之前添加一个空格,除了第一个

<xsl:template match="/">
  <header>
    <xsl:attribute name="class">
      <xsl:for-each select=".//header">
        <xsl:if test="position() > 1">
            <xsl:text> </xsl:text>
        </xsl:if>
        <xsl:value-of select="@class"/>
      </xsl:for-each>
    </xsl:attribute>
  </header>
</xsl:template>

如果希望类没有重复,请使用以下 XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  extension-element-prefixes="exsl">
  <xsl:output method="xml" encoding="UTF-8" indent="yes" />
  <xsl:template match="/">
    <document>
      <xsl:variable name="cls1">
        <xsl:for-each select=".//header/@class">
          <xsl:call-template name="tokenize">
            <xsl:with-param name="txt" select="."/>
          </xsl:call-template>  
        </xsl:for-each>
      </xsl:variable>
      <xsl:variable name="cls" select="exsl:node-set($cls1)"/>
      <header>
        <xsl:attribute name="class">
          <xsl:for-each select="$cls/*[not(preceding-sibling::* = .)]">
            <xsl:value-of select="."/>
            <xsl:if test="position() &lt; last()">
              <xsl:text> </xsl:text>
            </xsl:if>
          </xsl:for-each>
        </xsl:attribute>
      </header>
    </document>
  </xsl:template>
  <xsl:template name="tokenize">
    <xsl:param name="txt"/>
    <xsl:if test="$txt">
      <xsl:if test="contains($txt, ' ')">
        <cls>
          <xsl:value-of select="substring-before($txt, ' ')"/>
        </cls>
        <xsl:call-template name="tokenize">
          <xsl:with-param name="txt" select="substring-after($txt, ' ')"/>
        </xsl:call-template>
      </xsl:if>
      <xsl:if test="not(contains($txt, ' '))">
        <cls>
          <xsl:value-of select="$txt"/>
        </cls>
      </xsl:if>
    </xsl:if>
  </xsl:template>
</xsl:transform>
在 XSLT 1.0 中,

它比在 XSLT 2.0 中困难得多,但如您所见,这是可能的。

编辑

使用Muenchian分组的修订版本(灵感来自Michael的评论(:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  extension-element-prefixes="exsl">
  <xsl:output method="xml" encoding="UTF-8" indent="yes" />
  <xsl:variable name="cls1">
    <xsl:for-each select=".//header/@class">
      <xsl:call-template name="tokenize">
        <xsl:with-param name="txt" select="."/>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:variable>
  <xsl:variable name="cls2" select="exsl:node-set($cls1)"/>
  <xsl:key name="classKey" match="cls" use="."/>
  <xsl:template match="/">
    <document>
      <header>
        <xsl:attribute name="class">
          <xsl:for-each select="$cls2/*[generate-id() = generate-id(key('classKey', .)[1])]">
            <xsl:value-of select="."/>
            <xsl:if test="position() &lt; last()">
              <xsl:text> </xsl:text>
            </xsl:if>
          </xsl:for-each>
        </xsl:attribute>
      </header>
    </document>
  </xsl:template>
  <xsl:template name="tokenize">
    <xsl:param name="txt"/>
    <xsl:if test="$txt">
      <xsl:if test="contains($txt, ' ')">
        <cls>
          <xsl:value-of select="substring-before($txt, ' ')"/>
        </cls>
        <xsl:call-template name="tokenize">
          <xsl:with-param name="txt" select="substring-after($txt, ' ')"/>
        </xsl:call-template>
      </xsl:if>
      <xsl:if test="not(contains($txt, ' '))">
        <cls>
          <xsl:value-of select="$txt"/>
        </cls>
      </xsl:if>
    </xsl:if>
  </xsl:template>
</xsl:transform>

最新更新