简单的XSLT模板

时间:2011-02-09 10:31:22

标签: templates xslt

有XML文档:

<data>how;many;i;can;tell;you</data>

需要使用XSLT版本1获取XML

 <manydata>
     <onedata>how</onedata>
     <onedata>many</onedata>
     <onedata>i</onedata>
     <onedata>can</onedata>
     <onedata>tell</onedata>
     <onedata>you</onedata>
   </manydata>

我怎么做?

更新: 输出格式必须为 XML

4 个答案:

答案 0 :(得分:1)

<xsl:template match="data">
    <manydata>
        <!-- 
            empty <manydata/> will be generated,
            if <data/> without child text() 
        -->
        <xsl:apply-templates select="text()"/>
    </manydata>
</xsl:template>

<xsl:template match="data/text()">
    <!-- start point for recursion -->
    <xsl:call-template name="tokenize-string">
        <xsl:with-param name="separator" select="';'"/>
        <xsl:with-param name="string" select="text()"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="tokenize-string">
    <xsl:param name="separator"/>
    <xsl:param name="string"/>
    <xsl:variable name="string-before-separator" 
        select="substring-before( $string, $separator )"/>
    <onedata>
        <xsl:choose>
            <!-- if $separator presents in $string take first piece -->
            <xsl:when test="$string-before-separator">
                <xsl:value-of select="$string-before-separator"/>
            </xsl:when>
            <!-- take whole $string, if no $separator in the $string -->
            <xsl:otherwise>
                <xsl:value-of select="$string"/>
            </xsl:otherwise>
        </xsl:choose>
    </onedata>
    <!-- recursive call, if separator was found -->
    <xsl:if test="$string-before-separator">
        <xsl:call-template name="tokenize-string">
            <xsl:with-param name="separator" select="$separator"/>
            <xsl:with-param name="string" 
                select="substring-after( $string, $separator )"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

答案 1 :(得分:1)

这种递归解决方案可能是最短的之一:

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

 <xsl:template match="data">
  <manydata><xsl:apply-templates/></manydata>
 </xsl:template>

 <xsl:template match="text()" name="tokenize">
  <xsl:param name="pText" select="."/>
   <xsl:if test="string-length($pText)">
      <onedata>
       <xsl:value-of select=
        "substring-before(concat($pText,';'),';')"/>
      </onedata>
      <xsl:call-template name="tokenize">
       <xsl:with-param name="pText" select=
        "substring-after($pText,';')"/>
      </xsl:call-template>
     </xsl:if>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<data>how;many;i;can;tell;you</data>

产生了想要的正确结果:

<manydata>
   <onedata>how</onedata>
   <onedata>many</onedata>
   <onedata>i</onedata>
   <onedata>can</onedata>
   <onedata>tell</onedata>
   <onedata>you</onedata>
</manydata>

答案 2 :(得分:0)

试试这个:

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

  <xsl:template match="data">
   <xsl:element name="manydata">
      <xsl:call-template name="splitsemicolons">
        <xsl:with-param name="text" select="text()" />
      </xsl:call-template>
    </xsl:element>
  </xsl:template>

  <xsl:template name="splitsemicolons">
    <xsl:param name="text" />
    <xsl:choose>
      <xsl:when test="contains($text,';')">
        <xsl:element name="onedata">
          <xsl:value-of select="substring-before($text,';')" />
         </xsl:element>
         <xsl:call-template name="splitsemicolons">
           <xsl:with-param name="text" select="substring-after($text,';')" />
         </xsl:call-template>
       </xsl:when>
       <xsl:otherwise>
         <xsl:element name="onedata">
           <xsl:value-of select="$text" />
         </xsl:element>
       </xsl:otherwise>
     </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

这使用一个递归调用的命名模板,每次输出第一个;之前的内容,并在第一个;之后调用自身。如果没有;,它只会按原样输出任何内容。

答案 3 :(得分:0)

您可以使用XSLT extension library获取tokenize功能。以下是最终代码的样子:

<xsl:template match="/">
 <manydata>
 <xsl:for-each select="str:tokenize(data, ';')">
      <xsl:value-of select="." />
   </xsl:for-each> 
 </manydata>
</xsl:template>
</xsl:stylesheet>

请注意,您必须使用以下命令将扩展库导入XSLT:

<xsl:import href="path/str.xsl" />

在使用库函数之前。