XSLT:使用xsl:value-of-am我返回一个字符串或单个字符串的节点集?

时间:2015-09-02 21:22:15

标签: xml string xslt

我有一个模板,用于在给定的分隔符处拆分字符串:

<xsl:template name="SplitStringAtSeparator">
  <xsl:param name="stringToSplit"/>
  <xsl:param name="separatorCharacter" />
  <xsl:choose>
     <xsl:when test="contains($stringToSplit, $separatorCharacter)">
        <xsl:value-of select="substring-before($stringToSplit, $separatorCharacter)"/>
        <xsl:call-template name="SplitStringAtSeparator">
           <xsl:with-param name="stringToSplit"
                           select="substring-after($stringToSplit, $separatorCharacter)"/>
        </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
        <xsl:if test="$stringToSplit != ''">
           <xsl:value-of select="$stringToSplit"/>
        </xsl:if>
     </xsl:otherwise>
  </xsl:choose>
</xsl:template>

假设stringToSplit =&#39; 你好,这是一个要拆分的字符串&#39;而且我们要拆分空格字符,我是否会找回一个只留下空格字符的文本节点

hellothisisastringtosplit

或者我将获得一个可以迭代的文本节点的节点集?

node[1] = hello
node[2] = this
node[3] = is
node[4] = a 
node[5] = string 
node[6] = to 
node[7] = split

我应该注意,如果不是后者,那么后者就是我想要做的事情

2 个答案:

答案 0 :(得分:4)

让我们说你的输入文件是......

<root>
  <stringToSplit>hello this is a string to split</stringToSplit>
</root>

...并且您希望拆分stringToSplit的字符串内容并处理粒子。让我们说处理只是输出粒子的编号列表。以下是两个如何做到这一点的例子。一种解决方案是XSLT 1.0,另一种是XSLT 2。

XSLT 1.0解决方案

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:so="http://stackoverflow.com/questions/32363330"
  xmlns:exsl="http://exslt.org/common"
  version="1.0"
  exclude-result-prefixes="so exsl">

<xsl:output method="html" version="5" doctype-system="" encoding="utf-8" />
<xsl:strip-space elements="*" />  

<xsl:template match="/">
  <html>
    <head>
      <title>Hello! This is a string to split.</title>
    </head>
    <body>
      <h1>Hello! This is a string to split.</h1>
      <p>The following is an example of splitting a string in XSLT 1.0 and then processing each string part.</p>
      <h2>String parts</h2>
      <ol>
        <xsl:apply-templates select="root/stringToSplit" />
      </ol>
    </body>
  </html>
</xsl:template>

<xsl:template name="SplitStringAtSeparator">
  <xsl:param name="stringToSplit" />
  <xsl:param name="separatorCharacter" />
  <xsl:choose>
     <xsl:when test="contains($stringToSplit, $separatorCharacter)">
       <so:particle><xsl:value-of select="substring-before($stringToSplit, $separatorCharacter)"/></so:particle>
       <xsl:call-template name="SplitStringAtSeparator">
         <xsl:with-param name="stringToSplit" select="substring-after($stringToSplit, $separatorCharacter)" />
         <xsl:with-param name="separatorCharacter" select="$separatorCharacter" />
       </xsl:call-template>
     </xsl:when>
     <xsl:when test="$stringToSplit">
       <so:particle><xsl:value-of select="$stringToSplit"/></so:particle>
     </xsl:when>
  </xsl:choose>
</xsl:template>

<xsl:template match="stringToSplit">
  <xsl:variable name="split-string">
    <xsl:call-template name="SplitStringAtSeparator">
      <xsl:with-param name="stringToSplit" select="text()" />
      <xsl:with-param name="separatorCharacter" select="' '" />
    </xsl:call-template>
  </xsl:variable>
  <xsl:apply-templates select="exsl:node-set( $split-string)" mode="particle-processing" />
</xsl:template>

<xsl:template match="so:particle" mode="particle-processing">
  <li><xsl:value-of select="." /></li>
</xsl:template>

</xsl:stylesheet>   

XSLT 2解决方案

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

<xsl:output method="html" version="5" doctype-system="" encoding="utf-8" />
<xsl:strip-space elements="*" />  

<xsl:template match="/">
  <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
      <title>Hello! This is a string to split.</title>
    </head>
    <body>
      <h1>Hello! This is a string to split.</h1>
      <p>The following is an example of splitting a string in XSLT 2 and then processing each string part.</p>
      <h2>String parts</h2>
      <ol>
        <xsl:analyze-string select="root/stringToSplit/text()" regex="\S*">
          <xsl:matching-substring>
            <li><xsl:value-of select="."/></li>
          </xsl:matching-substring>
        </xsl:analyze-string>
      </ol>
    </body>
  </html>
</xsl:template>

</xsl:stylesheet>  

输出

在这两种情况下,您都可以获得输出文档,如...

<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Hello! This is a string to split.</title>
  </head>
  <body>
    <h1>Hello! This is a string to split.</h1>
    <p>The following is an example of splitting a string in XSLT 1.0 and then processing each string part.</p>
    <h2>String parts</h2>
    <ol>
      <li>hello</li>
      <li>this</li>
      <li>is</li>
      <li>a</li>
      <li>string</li>
      <li>to</li>
      <li>split</li>
    </ol>
  </body>
</html>

答案 1 :(得分:2)

我假设您正在使用XSLT 1.0。无法在XSLT 1.0(或一般的XML)中创建(仅)文本节点的节点集。如果要单独处理标记,则必须将它们创建为XML元素。

XSLT 1.0的另一个复杂因素是结果最初是结果树片段,而不是节点集。您必须使用扩展node-set()函数(几乎所有XSLT 1.0处理器都支持)将其转换为节点集。只有这样,您才能按位置对每个节点进行寻址。