XSLT 转换、字符串连接

发布于 2024-10-19 22:59:54 字数 1332 浏览 2 评论 0原文

我有下面的 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 中。

我正在尝试使用如下所示的内容,但坚持条件 &当 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>

感谢任何帮助。

I have the below 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>

When transforming with an XSLT, I need to concatenate the Abstract and Author fields, and show it like

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

The Abstract, Abstract1, Abstract2 may appear in any order in the xml.

I am trying to use something like below, but stuck on the condition & concatenation of string when Abstract, Abstract1 doesn't appear in the same order

<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>

Appreciate any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

寒江雪… 2024-10-26 22:59:54

此转换

<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 处于命名模式,并且应该以“拉式风格”使用——由调用者显式应用。

This transformation:

<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>

when applied on the provided XML document:

<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>

produces the wanted result:

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

Further refactoring:

<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>

A second refactoring (requested by the 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>

EDIT: The OP has requested that "all processing should be done within the template matching MT". While this is possible in simple cases (see @Alejandro's answer), doing all the processing in a single template matching MT opens big gaps of unknowns. For example, it may be required to process other MT elements in a different way and in this case such processing will not be done at all.

In more complex cases (such as when the elements and attributes come in any order, but the output must be sorted -- Abstract1, Abstract2, ..., Abstract-N), then the sort has to be specified explicitly and this has to be outside the template matching MT. Therefore, in the general case, it is not possible to produce the required output with code only within the template matching MT.

I would recommend that the single template matching MT be in a named mode and that it should be used in "pull style" -- applied explicitly by the caller.

归属感 2024-10-26 22:59:54
<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>
<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>
一身骄傲 2024-10-26 22:59:54

此样式表:

<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>
</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元素。

This stylesheet:

<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>
</xsl:text>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>

Output:

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

Note: Grouping by @N alphabetic content and parent generated id because I would expect several R elements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文