2011-09-15 42 views
10

如何在XSLT 1.0中拆分節點值?在xslt 1.0中拆分函數

<mark>1,2</mark> 

我需要在for循環中執行一些操作,使用split的每個輸出值。

<xsl:for-each select=""> </xsl:for-each>

如何做到這一點?

+0

數值中是否總是有兩個項,或者它是可變數? –

+0

它可能會有所不同。它是節點標記的值。 –

+0

好問題,+1。根據使用哪個版本的XSLT(1.0或2.0),可以通過遞歸處理或僅使用標準XPath 2.0函數'tokenize()'完成此操作。 –

回答

12

一XSLT 1.0解決方案

下面是僅使用xxx:node-set()擴展功能爲此在XSLT 1.0的一種方式:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="mark"> 
    <xsl:variable name="vrtfSplit"> 
    <xsl:apply-templates/> 
    </xsl:variable> 

    <xsl:for-each select="ext:node-set($vrtfSplit)/*"> 
    <processedItem> 
    <xsl:value-of select="10 * ."/> 
    </processedItem> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="text()" name="split"> 
    <xsl:param name="pText" select="."/> 
    <xsl:if test="string-length($pText) >0"> 
    <item> 
    <xsl:value-of select= 
     "substring-before(concat($pText, ','), ',')"/> 
    </item> 

    <xsl:call-template name="split"> 
    <xsl:with-param name="pText" select= 
    "substring-after($pText, ',')"/> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

當這個變換通貨膨脹被施加到下面的XML文檔

<mark>1,2,3,4,5</mark> 

的想要的,正確的輸出(每個項目乘以10)產生

II。 XSLT 2.0解決方案

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="mark"> 
    <xsl:for-each select="tokenize(., ',')"> 
    <processedItem> 
    <xsl:sequence select="10*xs:integer(.)"/> 
    </processedItem> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 
4

通過Dimitre Novatchev的交代是真棒,但我們也能做到這一點的更簡單的方法,而無需使用node-set()功能看看:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 


    <xsl:output omit-xml-declaration="yes" indent="yes"/> 



    <xsl:variable name="delimiter"> 
     <xsl:text>,</xsl:text> 
    </xsl:variable> 



    <xsl:template match="mark"> 
     <xsl:variable name="dataList"> 
      <xsl:value-of select="."/> 
     </xsl:variable> 
     <xsl:call-template name="processingTemplate"> 
      <xsl:with-param name="datalist" select="$dataList"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="processingTemplate"> 
     <xsl:param name="datalist"/> 


     <xsl:choose> 
     <xsl:when test="contains($datalist,$delimiter) "> 
       <xsl:element name="processedItem"> 
        <xsl:value-of select="substring-before($datalist,$delimiter) * 10"/> 
       </xsl:element> 
       <xsl:call-template name="processingTemplate"> 
        <xsl:with-param name="datalist" select="substring-after($datalist,$delimiter)"/> 
       </xsl:call-template> 
     </xsl:when> 
      <xsl:when test="string-length($datalist)=1"> 
       <xsl:element name="processedItem"> 
        <xsl:value-of select="$datalist * 10"/> 

        </xsl:element> 
      </xsl:when> 
     </xsl:choose>  

    </xsl:template> 
</xsl:stylesheet> 
0

此代碼將在XSLT 1.0 (拆分分隔的字符串它將適用於2.0,但不使用節點集。) 它還可以選擇性地抑制字符串 中的空元素或可選地大寫元素。

<!-- Example delimited string. --> 
<xsl:variable name="delimitedString" select="'a, b, c, , , d, e, f, g'"/> 

<!-- Create a node set where each node contains one of the elements from the 
    delimited string. --> 
<xsl:variable name="splitNodes"> 
    <xsl:call-template name="getNodeListFromDelimitedList"> 
    <xsl:with-param name="inStrList" select="$delimitedString"/> 
    <xsl:with-param name="delimiter" select="','"/> 
    <xsl:with-param name="suppressEmptyElements" select="false()"/> 
    <xsl:with-param name="upperCase" select="false()"/> 
    <xsl:with-param name="allTrim" select="false()"/> 
    </xsl:call-template>  
</xsl:variable> 

<!-- Use this for XSLT 1.0 only. --> 
<xsl:variable name="splitNodesList" select="msxml:node-set($splitNodes)"/> 

<!-- Use the split node list to do something. For example, create a string like 
    the delimited string, but without the delimiters. --> 
<xsl:variable name="nonDelimitedString"> 
    <xsl:for-each select="$splitNodesList/element"> 
    <xsl:value-of select="."/> 
    </xsl:for-each> 
</xsl:variable> 


<!-- Do something with the nonDelimitedString. --> 

<!-- 
***************************************************************************************** 

This template converts a delimited string list to a node list as follows: 

Each value in the delimited input string is extracted from the string. Then, a node is 
created to contain the value. The name of the node is 'element', and it is added to the 
list. To use this template, create an variable and call this template from within the variable. 
If you are using XSLT version 1.0, convert the node list to a node set using the node-set 
function. You can access the element as follows: $SomeVariableNodeSet/element 

***************************************************************************************** 
--> 
<xsl:template name="getNodeListFromDelimitedList"> 
    <!-- Delimited string with one or more delimiters. --> 
    <xsl:param name="inStrList"/> 
    <!-- The delimiter. --> 
    <xsl:param name="delimiter" select="'|'"/> 
    <!-- Set to true to suppress empty elements from being added to node list. Otherwise, set to 'false'.--> 
    <xsl:param name="suppressEmptyElements" select="true()"/> 
    <!-- Set to true to upper case the strings added to the node list. --> 
    <xsl:param name="upperCase" select="false()"/> 
    <!-- Set to true to left trim and right trim the strings added to the nodes list. --> 
    <xsl:param name="allTrim" select="false()"/> 

    <xsl:variable name="element"> 
    <xsl:choose> 
     <xsl:when test="contains($inStrList,$delimiter)"> 
     <xsl:value-of select="substring-before($inStrList,$delimiter)"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="$inStrList"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <!-- Write out the element based on parameters. --> 
    <xsl:if test="not($suppressEmptyElements) or normalize-space($element) != ''"> 
    <!-- Put the element in the list. --> 
    <xsl:element name="element"> 
     <xsl:choose> 
     <xsl:when test="$allTrim"> 
      <xsl:call-template name="all-trim"> 
      <xsl:with-param name="inStr" select="$element"/> 
      <xsl:with-param name="upperCase" select="$upperCase"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:when test="$upperCase"> 
      <xsl:value-of select="translate($element, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$element"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:element> 
    </xsl:if> 

    <xsl:if test="contains($inStrList,$delimiter)"> 
    <!-- Call template recursively to process the next element. --> 
    <xsl:call-template name="getNodeListFromDelimitedList"> 
     <xsl:with-param name="inStrList" select="substring-after($inStrList,$delimiter)"/> 
     <xsl:with-param name="delimiter" select="$delimiter"/> 
     <xsl:with-param name="suppressEmptyElements" select="$suppressEmptyElements"/> 
     <xsl:with-param name="upperCase" select="$upperCase"/> 
     <xsl:with-param name="allTrim" select="$allTrim"/> 
    </xsl:call-template> 
    </xsl:if> 

</xsl:template> 


<!-- 
***************************************************************************************** 
This template trims the blanks from the left and right sides of a string. 
***************************************************************************************** 
--> 
<xsl:template name="all-trim"> 
    <!-- The string that you want to all trim. --> 
    <xsl:param name="inStr"/> 
    <xsl:param name="upperCase" select="false()"/> 

    <xsl:variable name="leftTrimmed"> 
    <xsl:call-template name="left-trim"> 
     <xsl:with-param name="inStr" select="$inStr"/> 
    </xsl:call-template> 
    </xsl:variable> 

    <xsl:variable name="rightTrimmed"> 
    <xsl:call-template name="right-trim"> 
     <xsl:with-param name="inStr" select="$leftTrimmed"/> 
    </xsl:call-template> 
    </xsl:variable> 

    <xsl:choose> 
    <xsl:when test="$upperCase"> 
     <xsl:value-of select="translate($rightTrimmed, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="$rightTrimmed"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<!-- 
***************************************************************************************** 
This template trims the blanks from the left side of a string. 
***************************************************************************************** 
--> 
<xsl:template name="left-trim"> 
    <!-- The string you want to left trim. --> 
    <xsl:param name ="inStr"/> 

    <xsl:choose> 
    <xsl:when test="$inStr!=''"> 
     <xsl:variable name="temp" select="substring($inStr, 1, 1)"/> 
     <xsl:choose> 
     <xsl:when test="$temp=' '"> 
      <xsl:choose> 
      <xsl:when test="string-length($inStr) &gt; 1"> 
       <xsl:call-template name="left-trim"> 
       <xsl:with-param name="inStr" select="substring($inStr, 2, string-length($inStr)-1)"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="''"/> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$inStr"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="''"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 


<!-- 
***************************************************************************************** 
This template trims the blanks from the right side of a string. 
***************************************************************************************** 
--> 
<xsl:template name="right-trim"> 
    <!-- The string you want to right trim. --> 
    <xsl:param name ="inStr"/> 

    <xsl:choose> 
    <xsl:when test="$inStr!=''"> 
     <xsl:variable name="temp" select="substring($inStr, string-length($inStr), 1)"/> 
     <xsl:choose> 
     <xsl:when test="$temp=' '"> 
      <xsl:choose> 
      <xsl:when test="string-length($inStr) &gt; 1"> 
       <xsl:call-template name="right-trim"> 
       <xsl:with-param name="inStr" select="substring($inStr, 1, string-length($inStr)-1)"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="''"/> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$inStr"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="''"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template>