Drew
Drew

Reputation: 159

XSLT/XPath: how to use xsl:apply-templates on all but specific elements

I have the following XML code:

<detaileddescription>
   <para>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum aliquam
   interdum erat, <computeroutput>monospace output</computeroutput> eget rhoncus nunc
   porttitor ut. Ut ac metus sed erat rutrum dignissim.
   <parameterlist kind="param">
       <parameteritem>
           <parameternamelist>
               <parametername>item1</parametername>
           </parameternamelist>
           <parameterdescription>
               <para>Param description.</para>
           </parameterdescription>
        </parameteritem>
    </parameterlist>
    <simplesect kind="return">
        <para>
            <computeroutput>ERR</computeroutput> mattis nunc sed velit ultricies
            volutpat. Suspendisse potenti. Vivamus nec ligula blandit urna lobortis   
            tempus.
        </para>
     </simplesect>
     </para>
 </detaileddescription>

I'd like to use xsl:apply-templates only to the text node child of the detaileddescription/para element and the <computeroutput> element that's inside the text node. In other words, I want to apply-templates only to the following content:

   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum aliquam
   interdum erat, <computeroutput>monospace output</computeroutput> eget rhoncus nunc
   porttitor ut. Ut ac metus sed erat rutrum dignissim.

Can anyone show me how to do this using XSLT 2.0 and XPath 2.0?

Upvotes: 3

Views: 3295

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243569

This transformation:

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

 <xsl:template match="/">
  <xsl:apply-templates select="*/para[1]/(text()|computeroutput)"/>
 </xsl:template>

 <xsl:template match="computeroutput">
  <xsl:sequence select="."/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<detaileddescription>
   <para>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum aliquam
   interdum erat, <computeroutput>monospace output</computeroutput> eget rhoncus nunc
   porttitor ut. Ut ac metus sed erat rutrum dignissim.
   <parameterlist kind="param">
       <parameteritem>
           <parameternamelist>
               <parametername>item1</parametername>
           </parameternamelist>
           <parameterdescription>
               <para>Param description.</para>
           </parameterdescription>
        </parameteritem>
    </parameterlist>
    <simplesect kind="return">
        <para>
            <computeroutput>ERR</computeroutput> mattis nunc sed velit ultricies
            volutpat. Suspendisse potenti. Vivamus nec ligula blandit urna lobortis
            tempus.
        </para>
     </simplesect>
     </para>
 </detaileddescription>

processes (applies templates to) only the wanted nodes and for this demo puposes just copies these nodes to the output:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum aliquam
   interdum erat, <computeroutput>monospace output</computeroutput> eget rhoncus nunc
   porttitor ut. Ut ac metus sed erat rutrum dignissim.

Upvotes: 1

If I understand your question correctly, this should work:

<xsl:apply-templates select="detaileddescription/para/(text()|computeroutput)"/>

of course, depending on the context note. Otherwise, you could also mean the corresponding tempate that will fit only those elements you want:

<xsl:template match="detaileddescription/para/(text()|computeroutput)"/>
  <xsl:copy-of select="." /> 
  <!-- or whatever you want to do with it -->
</xsl:template>

Hope this helps, R

Upvotes: 2

mindandmedia
mindandmedia

Reputation: 6825

here is one, although probably not the best way to do it. i baked you a cake

i created a copy-template, which copies everything and the last two templates are stop-templates, that don't produce any output.

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="detaileddescription">
  <xsl:apply-templates select="para"/>
</xsl:template>

<xsl:template match="para">
    <xsl:apply-templates select="@*|node()"/>
</xsl:template>

<xsl:template match="parameterlist"/>
<xsl:template match="simplesect"/>

i edited in the second template: this will remove (or rather not copy) the <detaileddescription> tag.

Upvotes: 2

Related Questions