XSL以两种不同的方式为同一文档中的两种不同情况转换相同的元素

时间:2018-01-02 16:20:11

标签: xml xslt

我有一些XML文本,如下所示,我正在使用XSL 3.0进行转换:

<deposition>
  <seg>Lorem 
    <persName>P<supplied>etrus</supplied> Fabri 
       <roleName>textor</roleName> 
       <sic>apud</sic> 
       de Sancto Jacobo<persName> ipsum dolor sit amet, 
    consectetur  adipiscing elit. Praesent vitae congue leo, 
    nec varius mauris. Vestibulum elementum arcu non 
    ultricies aliquam.</seg>
  <seg>Ut pharetra bibendum ipsum, porttitor porttitor 
    velit pharetra quis. Aenean vel dolor purus. Praesent 
    aliquam viverra tellus in condimentum.</seg>
</deposition>

转型目标如下。此转换会从''的转换版本中添加新的<deposition-title>,而<persName>本身会在<seg>内转换:

<deposition>
  <deposition-title>P. Fabri de Sancto Jacobo<deposition-title>
  <seg>Lorem P[etrus] Fabri textor de Sancto Jacobo 
    ipsum dolor sit amet, 
    consectetur  adipiscing elit. Praesent vitae congue leo, 
    nec varius mauris. Vestibulum elementum arcu non 
    ultricies aliquam.</seg>
  <seg>Ut pharetra bibendum ipsum, porttitor porttitor 
    velit pharetra quis. Aenean vel dolor purus. Praesent 
    aliquam viverra tellus in condimentum.</seg>
</deposition>

显然,这次'处理'<persName>(以及它的子元素)两次。

我目前有模板转换<seg>内的元素,例如:

<xsl:template match="supplied">
  <xsl:text>[<xsl:text><xsl:apply-templates/><xsl:text>]<xsl:text>
</xsl:template>

<xsl:template match="sic"/>

但是,当创建新的<deposition-title>元素时,我不知道如何在模板副本中的非常简单的<xsl:value-of select="persName">之外执行此操作:

<xsl:template match="deposition">
  <xsl:copy>
     <deposition-title><xsl:value-of select="persName"></deposition-title>
     <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

只是转储text()节点而不处理它们(如上所述):

<deposition-title>Petrus Fabri textor apud de Sancto Jacobo</deposition-title>

理想情况下,我想调用不同版本的模板来区别对待元素。

有没有办法以某种方式为相同的元素制作各种模板以供不同情况下使用和调用?

添加了一个示例:

对于seg元素,处理保留 roleName元素的模板:

<xsl:template match="roleName">
  <xsl:text>[<xsl:text><xsl:apply-templates/><xsl:text>]<xsl:text>
</xsl:template>

但是在创建新的deposit-title元素时,请使用删除 roleName元素的模板:

 <xsl:template match="roleName"/>

1 个答案:

答案 0 :(得分:1)

你可以这样做......

<deposition-title>
   <xsl:value-of select="seg/persName/text()" separator=" " />
</deposition-title>

因此,只获取seg/persName的直接子文本节点。虽然,你也可能想要整理空白......

<deposition-title>
    <xsl:value-of select="seg/persName/text()[normalize-space()]/normalize-space()" />
</deposition-title>

请注意,这假设您只有一个segpersName,否则您会将多个名称全部合并为一个。

如果您确实想使用不同的模板,而不是简单地输出文字,则可以使用mode

<xsl:template match="deposition">
  <xsl:copy>
     <deposition-title>
         <xsl:apply-templates select="seg/persName/node()" mode="title" />
     </deposition-title>
     <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

<xsl:template match="supplied" mode="title">
    <xsl:text>.</xsl:text>
</xsl:template>

<xsl:template match="roleName" mode="title"/>

<xsl:template match="node()" mode="title">
    <xsl:text> </xsl:text>
    <xsl:value-of select="normalize-space()" />
</xsl:template>   

您可以将mode="#all"用于模板,而不是在此处的任何模式中使用。

<xsl:template match="sic" mode="#all" />