2010-07-26 36 views
24

Làm thế nào để bạn tách một chuỗi dựa trên một số dấu phân cách?Xslt có hàm split() không?

Cho một xâu Topic1,Topic2,Topic3, tôi muốn chia chuỗi dựa trên , để generate:

Topic1 Topic2 Topic3 
+1

có thể bản sao của [XSLT có một hàm Split() không?] (http://stackoverflow.com/questions/136500/does-xslt-have-a-split-function) –

Trả lời

32

Trong XSLT 1.0, bạn phải xây dựng một mẫu đệ quy. stylesheet này:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="text/text()" name="tokenize"> 
     <xsl:param name="text" select="."/> 
     <xsl:param name="separator" select="','"/> 
     <xsl:choose> 
      <xsl:when test="not(contains($text, $separator))"> 
       <item> 
        <xsl:value-of select="normalize-space($text)"/> 
       </item> 
      </xsl:when> 
      <xsl:otherwise> 
       <item> 
        <xsl:value-of select="normalize-space(substring-before($text, $separator))"/> 
       </item> 
       <xsl:call-template name="tokenize"> 
        <xsl:with-param name="text" select="substring-after($text, $separator)"/> 
       </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Input:

<root> 
<text>Item1, Item2, Item3</text> 
</root> 

Output:

<root> 
    <text> 
     <item>Item1</item> 
     <item>Item2</item> 
     <item>Item3</item> 
    </text> 
</root> 

Trong XSLT 2.0, bạn có chức năng tokenize() lõi. Vì vậy, kiểu này:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="text/text()" name="tokenize"> 
     <xsl:param name="separator" select="','"/> 
     <xsl:for-each select="tokenize(.,$separator)"> 
       <item> 
        <xsl:value-of select="normalize-space(.)"/> 
       </item> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Kết quả:

<root> 
    <text> 
     <item>Item1</item> 
     <item>Item2</item> 
     <item>Item3</item> 
    </text> 
</root> 
+0

Vui lòng mô tả mẫu đầu tiên đang làm gì – ziggy

+0

@ziggy Mẫu đầu tiên là một chuyển đổi nhận dạng, nghĩa là nó chỉ tạo ra một bản sao chính xác của tất cả các nút và các thuộc tính từ nguồn XML. – skrtxao

2

Không có split chức năng, nhưng bạn có thể sử dụng một mẫu đệ quy với substring-beforesubstring-after viết riêng của bạn.

Xem bài viết this để biết chi tiết.

3

Sử dụng fn:tokenize

+6

Tính năng này chỉ hợp lệ cho xslt 2.0 – ziggy

1

Cảm ơn bạn user357812. Tôi sử dụng mẫu tốt đẹp của bạn với rất ít tùy biến để làm cho nó chung chung:

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

    <!-- Main template --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()" mode="tokenize-children" /> 
     </xsl:copy> 
    </xsl:template> 

    <!-- Split child nodes --> 
    <xsl:template match="*" mode="tokenize-children"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*" /> 
      <xsl:apply-templates select="*" mode="tokenize" /> 
     </xsl:copy> 
    </xsl:template> 

    <!-- Tokenize text node of child nodes --> 
    <xsl:template match="*/text()" name="tokenize" mode="tokenize"> 
     <xsl:param name="text" select="."/> 
     <xsl:param name="separator" select="','"/> 
     <xsl:variable name="item" select="name(..)" /> 
     <xsl:choose> 
      <xsl:when test="not(contains($text, $separator))"> 
       <xsl:element name="{$item}"> 
        <xsl:value-of select="normalize-space($text)"/> 
       </xsl:element> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:element name="{$item}"> 
        <xsl:value-of select="normalize-space(substring-before($text, $separator))"/> 
       </xsl:element> 
       <xsl:call-template name="tokenize"> 
        <xsl:with-param name="text" select="substring-after($text, $separator)"/> 
       </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 
0

Tùy thuộc vào những gì xử lý XSL bạn đang sử dụng, bạn có thể truy cập vào các chức năng mở rộng str:tokenize().

Vì vậy, để chia Topic1,Topic2,Topic3 trên , làm;

<xsl:copy-of select="str:tokenize('Topic1,Topic2,Topic3', ',')"/> 

sẽ cho kết quả;

<token>Topic1</token> 
<token>Topic2</token> 
<token>Topic3</token> 
1

XSLT 1.0
tôi cần một biến thể nhẹ so với câu trả lời khác đưa ra ở đây.

Input:

1, 2, 3

Ouput:

1, 2 và 3

Input:

Output

Nếu delimiter là không gian thay vì dấu phẩy, nó vẫn sẽ làm việc.

Input:

Ouput:

1, 2 và 3

Tôi vừa tạo một mẫu được sửa đổi một chút.

<xsl:template name="tokenizeString"> 
<xsl:param name="list"/> 
<xsl:param name="delimiter"/> 
<xsl:choose> 
    <xsl:when test="contains($list, $delimiter)">  
     <xsl:variable name="listLength" select="string-length($list)" /> 
     <xsl:variable name="listLengthWithoutDelimiters" select="string-length(translate($list, $delimiter,''))" /> 
     <xsl:variable name="noOfDelimiters" select="($listLength - $listLengthWithoutDelimiters)" /> 

     <xsl:value-of select="substring-before($list,$delimiter)"/> 
     <xsl:if test="$noOfDelimiters > 1">, </xsl:if> 
     <xsl:if test="$noOfDelimiters = 1"> and </xsl:if> 
     <xsl:call-template name="tokenizeString"> 
      <xsl:with-param name="list" select="substring-after($list,$delimiter)"/> 
      <xsl:with-param name="delimiter" select="$delimiter"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:choose> 
      <xsl:when test="$list = ''"> 
       <xsl:text/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$list"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:otherwise> 
</xsl:choose> 

Mẫu có thể được gọi như sau khi delimiter là dấu phẩy

<xsl:call-template name="tokenizeString"> 
    <xsl:with-param name="list">1, 2, 3</xsl:with-param> 
    <xsl:with-param name="delimiter"> 
     <xsl:value-of select="','" /> 
    </xsl:with-param> 
</xsl:call-template> 

Mẫu có thể được gọi như sau khi delimiter là không gian

<xsl:call-template name="tokenizeString"> 
    <xsl:with-param name="list">1 2 3</xsl:with-param> 
    <xsl:with-param name="delimiter"> 
     <xsl:value-of select="' '" /> 
    </xsl:with-param> 
</xsl:call-template>