XSLT转换,字符串连接

时间:2011-03-02 14:29:06

标签: xslt string-concatenation

我有以下xml

<R N="14" MIME="application/pdf">
    <RK>7</RK>
    <MT N="Abstract"
        V="Lorem Ipsum is simply dummy text of the printing " />
    <MT N="Abstract1"
  V="and typesetting industry. Lorem Ipsum has been the industry's standard "/>
    <MT N="Author" V="Bernard Shaw;" />
    <MT N="Author1" V="Mark Twain" />
    <MT N="Abstract2"
   V="dummy text ever since the 1500s, when an unknown printer took a galley"/>
    <LANG>en</LANG>
</R>

使用XSLT进行转换时,我需要连接Abstract和Author字段,并将其显示为

Abstract: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley

Author: Bernard Shaw;Mark Twain

Abstract,Abstract1,Abstract2可以在xml中以任何顺序出现。

我正在尝试使用类似下面的东西,但坚持使用条件&amp;当Abstract,Abstract1没有以相同的顺序出现时串联串联

<xsl:template match="MT">
    <xsl:if test="(some generic condition to display Title)">
        <br/>
        <span class="f">
            <xsl:value-of select="@N"/>
        </span>
    </xsl:if>
    <xsl:value-of select="@V"/>
</xsl:template>

感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

此转化

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

 <xsl:template match="/">
     Abstract: <xsl:text/>
     <xsl:for-each select="*/MT[starts-with(@N, 'Abstract')]">
       <xsl:value-of select="@V"/>
     </xsl:for-each>
   Author: <xsl:text/>
     <xsl:for-each select="*/MT[starts-with(@N, 'Author')]">
       <xsl:value-of select="@V"/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<R N="14" MIME="application/pdf">
    <RK>7</RK>
    <MT N="Abstract" V="Lorem Ipsum is simply dummy text of the printing " />
    <MT N="Abstract1" V="and typesetting industry. Lorem Ipsum has been the industry's standard " />
    <MT N="Author" V="Bernard Shaw;" />
    <MT N="Author1" V="Mark Twain" />
    <MT N="Abstract2" V="dummy text ever since the 1500s, when an unknown printer took a galley" />
    <LANG>en</LANG>
</R>

产生想要的结果:

Abstract: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley
Author: Bernard Shaw;Mark Twain

进一步重构

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

 <xsl:template match="/">
     Abstract: <xsl:text/>
     <xsl:call-template name="concatAttributes"/>
   Author: <xsl:text/>
     <xsl:call-template name="concatAttributes">
      <xsl:with-param name="pKeyStartString" select="'Author'"/>
     </xsl:call-template>
 </xsl:template>

 <xsl:template name="concatAttributes">
  <xsl:param name="pKeyAttribName" select="'N'"/>
  <xsl:param name="pKeyStartString" select="'Abstract'"/>
  <xsl:param name="pValueAttribName" select="'V'"/>

     <xsl:for-each select=
      "*/MT[starts-with(@*[name()=$pKeyAttribName], $pKeyStartString)]">
       <xsl:value-of select="@*[name()=$pValueAttribName]"/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

第二次重构(OP请求):

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>
    <xsl:variable name="vAbstract">
        <xsl:apply-templates mode="retrieve" select="//MT"/>
    </xsl:variable>
    <xsl:variable name="vAuthors">
        <xsl:apply-templates mode="retrieve" select="//MT">
            <xsl:with-param name="pKeyStartString" select="'Author'"/>
        </xsl:apply-templates>
    </xsl:variable>

    <xsl:template match="/">
     Abstract: <xsl:value-of select="$vAbstract"/>
     Authors:: <xsl:value-of select="$vAuthors"/>
    </xsl:template>

    <xsl:template match="MT" mode="retrieve">
        <xsl:param name="pKeyAttribName" select="'N'"/>
        <xsl:param name="pKeyStartString" select="'Abstract'"/>
        <xsl:param name="pValueAttribName" select="'V'"/>
        <xsl:if test="starts-with(@*[name()=$pKeyAttribName], $pKeyStartString)">
            <xsl:value-of select="@*[name()=$pValueAttribName]"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

编辑:OP已请求“所有处理都应在匹配MT的模板中完成”。虽然在简单的情况下这是可能的(参见@Alejandro的答案),但在匹配MT的单个模板中进行所有处理会打开未知数的巨大空白。例如,可能需要以不同的方式处理其他MT元素,在这种情况下,根本不会进行此类处理。

在更复杂的情况下(例如当元素和属性以任何顺序排列,但输出必须排序 - Abstract1,Abstract2,...,Abstract-N)时,必须明确指定排序,这必须在匹配MT的模板之外。 因此,在一般情况下,只能在匹配MT的模板中使用代码生成所需的输出。

我建议匹配MT的单个模板处于命名模式,并且应该在“拉式”中使用 - 由调用者明确应用。

答案 1 :(得分:0)

<xsl:for-each select="MT[starts-with(@N, 'Abstract')]">
    <xsl:if test="position() = 1">
        <xsl:value-of select="@N"/>:
    </xsl:if>
    <xsl:value-of select="@V"/>
</xsl:for-each>

答案 2 :(得分:0)

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kMtByAlphaN"
             match="MT"
             use="concat(generate-id(..),'+',translate(@N,'1234567890',''))"/>
    <xsl:template match="MT[count(.|key('kMtByAlphaN',
                                        concat(
                                           generate-id(..),'+',
                                           translate(@N,'1234567890','')
                                        )
                                    )[1]
                            ) = 1
                         ]">
        <xsl:variable name="vName"
                      select="translate(@N,'1234567890','')"/>
        <xsl:value-of select="concat($vName,': ')"/>
        <xsl:apply-templates select="key('kMtByAlphaN',
                                             concat(generate-id(..),'+',$vName)
                                     )/@V"/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>

输出:

Abstract: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley
Author: Bernard Shaw;Mark Twain

注意:按@N字母内容和父级生成的ID进行分组,因为我希望有多个R元素。