2013-03-17 35 views
1

我遇到了非常簡單的XSLT轉換問題。讓我們假設這是輸入XML文檔:XSLT:使用索引對字符串進行迭代

<root> 
    <myString>ABBCD</myString> 
</root> 

輸出XML應該是:

<root> 
    <myCharacters> 
     <character> 
      <id>1</id> 
      <value>A</value> 
     </character> 
     <character> 
      <id>2</id> 
      <value>B</value> 
     </character> 
     <character> 
      <id>3</id> 
      <value>B</value> 
     </character> 
     <character> 
      <id>4</id> 
      <value>C</value> 
     </character> 
     <character> 
      <id>5</id> 
      <value>D</value> 
     </character> 
    </myCharacters> 
</root> 

有沒有一種簡單的方法在它分裂這樣的字符串和增量指標?

+0

一個簡單的方法將做一個VBscript函數調用inb你的xslt,它將取值並返回一組節點。 – PSL 2013-03-17 18:30:38

回答

3

它在XSLT 2.0很容易...

XML輸入

<root> 
    <myString>ABBCD</myString> 
</root> 

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="myString"> 
     <myCharacters> 
      <xsl:analyze-string select="." regex="."> 
      <xsl:matching-substring> 
       <character> 
        <id><xsl:value-of select="position()"/></id> 
        <value><xsl:value-of select="."/></value> 
       </character> 
      </xsl:matching-substring> 
     </xsl:analyze-string> 
     </myCharacters> 
    </xsl:template> 

</xsl:stylesheet> 

XML輸出

<root> 
    <myCharacters> 
     <character> 
     <id>1</id> 
     <value>A</value> 
     </character> 
     <character> 
     <id>2</id> 
     <value>B</value> 
     </character> 
     <character> 
     <id>3</id> 
     <value>B</value> 
     </character> 
     <character> 
     <id>4</id> 
     <value>C</value> 
     </character> 
     <character> 
     <id>5</id> 
     <value>D</value> 
     </character> 
    </myCharacters> 
</root> 

1.0也不可怕。你可以使用遞歸模板。下面將產生相同的輸出:

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="myString"> 
     <myCharacters> 
      <xsl:call-template name="analyzeString"> 
       <xsl:with-param name="string" select="."/> 
      </xsl:call-template> 
     </myCharacters> 
    </xsl:template> 

    <xsl:template name="analyzeString"> 
     <xsl:param name="pos" select="1"/> 
     <xsl:param name="string"/> 
     <character> 
      <id><xsl:value-of select="$pos"/></id> 
      <value><xsl:value-of select="substring($string,1,1)"/></value> 
     </character> 
     <xsl:if test="string-length($string)>=2"> 
      <xsl:call-template name="analyzeString"> 
       <xsl:with-param name="pos" select="$pos+1"/> 
       <xsl:with-param name="string" select="substring($string,2)"/> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 
+0

+1(您幾乎完全貼出了XSLT 1。0解決方案在完成寫作之前,我正在工作幾秒鐘;-) – 2013-03-17 18:46:54

+0

@IanRoberts - 謝謝。我知道有人會有一個1.0的答案,所以我首先做了2.0的答案。我也很幸運地獲得了1.0的答案。 :-) – 2013-03-17 18:48:48

+0

這是非常好的解決方案,謝謝 – Mariusz 2013-03-17 19:08:09

1

I. XSLT 1.0解

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:variable name="vStyle" select="document('')"/> 

<xsl:template match="myString"> 
    <xsl:variable name="vStr" select="."/> 
    <root> 
    <myCharacters> 
     <xsl:for-each select= 
     "($vStyle//node()|$vStyle//@*|$vStyle//namespace::*) 
         [not(position() > string-length($vStr))]"> 

     <character> 
      <id><xsl:value-of select="position()"/></id> 
      <value><xsl:value-of select="substring($vStr,position(),1)"/></value> 
     </character> 
     </xsl:for-each> 
    </myCharacters> 
    </root> 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<root> 
    <myString>ABBCD</myString> 
</root> 

有用,正確的結果產生:

<root> 
    <myCharacters> 
     <character> 
     <id>1</id> 
     <value>A</value> 
     </character> 
     <character> 
     <id>2</id> 
     <value>B</value> 
     </character> 
     <character> 
     <id>3</id> 
     <value>B</value> 
     </character> 
     <character> 
     <id>4</id> 
     <value>C</value> 
     </character> 
     <character> 
     <id>5</id> 
     <value>D</value> 
     </character> 
    </myCharacters> 
</root> 

可替代地,與FXSL一個可以使用str-map模板這樣的:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:testmap="testmap" xmlns:f="http://fxsl.sf.net/" 
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="xsl f ext testmap"> 
    <xsl:import href="str-dvc-map.xsl"/> 
    <testmap:testmap/> 
    <xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/> 

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

    <xsl:template match="myString"> 
    <xsl:variable name="vrtfChars"> 
    <xsl:call-template name="str-map"> 
     <xsl:with-param name="pFun" select="$vTestMap"/> 
     <xsl:with-param name="pStr" select="."/> 
    </xsl:call-template> 
    </xsl:variable> 

    <myCharacters> 
     <xsl:apply-templates select="ext:node-set($vrtfChars)/*"/> 
    </myCharacters> 
    </xsl:template> 

    <xsl:template name="enumChars" match="*[namespace-uri() = 'testmap']" 
    mode="f:FXSL"> 
     <xsl:param name="arg1"/> 
     <character> 
      <value><xsl:value-of select="$arg1"/></value> 
     </character> 
    </xsl:template> 

    <xsl:template match="character"> 
    <character> 
     <id><xsl:value-of select="position()"/></id> 
     <xsl:copy-of select="*"/> 
    </character> 
    </xsl:template> 
</xsl:stylesheet> 

以產生相同的正確的結果

<myCharacters> 
    <character> 
     <id>1</id> 
     <value>A</value> 
    </character> 
    <character> 
     <id>2</id> 
     <value>B</value> 
    </character> 
    <character> 
     <id>3</id> 
     <value>B</value> 
    </character> 
    <character> 
     <id>4</id> 
     <value>C</value> 
    </character> 
    <character> 
     <id>5</id> 
     <value>D</value> 
    </character> 
</myCharacters> 

二, XSLT 2.0解決方案 - 比其他的答案更短,更簡單:

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

<xsl:template match="myString"> 
    <root> 
    <myCharacters> 
     <xsl:for-each select="string-to-codepoints(.)"> 
     <character> 
      <id><xsl:value-of select="position()"/></id> 
      <value><xsl:value-of select="codepoints-to-string(.)"/></value> 
     </character> 
     </xsl:for-each> 
    </myCharacters> 
    </root> 
</xsl:template> 
</xsl:stylesheet> 

當在同一個XML文檔(以上)應用時產生想要的,正確的結果:

<root> 
    <myCharacters> 
     <character> 
     <id>1</id> 
     <value>A</value> 
     </character> 
     <character> 
     <id>2</id> 
     <value>B</value> 
     </character> 
     <character> 
     <id>3</id> 
     <value>B</value> 
     </character> 
     <character> 
     <id>4</id> 
     <value>C</value> 
     </character> 
     <character> 
     <id>5</id> 
     <value>D</value> 
     </character> 
    </myCharacters> 
</root>