jbrehr
jbrehr

Reputation: 815

XSL transforming the same element in two different ways for two different cases in same document

I have some XML text that looks like below, which I am transforming with 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>

The transformation objective is below. This transformation adds a new <deposition-title> from a transformed version of '', and <persName> itself is transformed within <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>

Obviously this 'treating' the <persName> (and it's children element) twice.

I currently have templates transforming the elements inside <seg>, for example:

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

<xsl:template match="sic"/>

But when it comes time to create the new <deposition-title> element, I'm at a loss how to do it outside a very simple <xsl:value-of select="persName"> in a template copy:

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

Which just dumps out the text() nodes without processing them (as needed above):

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

Ideally I'd like to call different versions of the templates to treat the elements differently.

Is there a way of somehow making a variety of templates for the same element for use and calling in different cases?

Added an example:

For the seg element, process this template which keeps roleName element:

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

But in creating the new deposition-title element, use this template which removes the roleName element:

 <xsl:template match="roleName"/>

Upvotes: 0

Views: 38

Answers (1)

Tim C
Tim C

Reputation: 70598

You could do this...

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

So, only get the direct child text nodes of seg/persName. Although, you might want to tidy up the whitespace too...

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

Note, this assumes you only have one seg with a persName, otherwise you will get multiple names all put together as one.

If you do want to use different templates, rather than simply output text, you could make use of 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>   

You could use mode="#all" for templates than can be used in any mode here.

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

Upvotes: 1

Related Questions