Marc Sharma
Marc Sharma

Reputation: 17

Process an element anywhere in the xml document with xslt

I have a xml file that is basically the data of an article. I want to transform it using xslt.

My question: how do I process an element through xslt anywhere, at any depth in the xml document?

My research led me to find about the identity template but my attempt to use it proved unfructful. Here is something I tried:

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

<xsl:template match="em">
blabla
</xsl:template>

But it didn't replace the em content with blabla.

I also found out that validating an element anywhere is not something possible to do with a xsd schema. But I hope the answer is different for xslt.

Minimal Working Example:

<?xml version="1.0"?>
<doc>
    <foo>text <em>italics</em> anything</foo>
    <tag>text <foo><em>italics</em> stuff</foo></tag>
</doc>

I would like for instance to have <em>foo</em> replaced by <it>foo</it> or \emph{foo} (while of course doing other transformation on the document).

Upvotes: 1

Views: 417

Answers (2)

kjhughes
kjhughes

Reputation: 111561

Your XSLT already works as requested.

Here's a complete example that replaces em with it:

XML in

<?xml version="1.0"?>
<doc>
    <foo>text <em>italics</em> anything</foo>
    <tag>text <foo><em>italics</em> stuff</foo></tag>
</doc>

XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

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

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

</xsl:stylesheet>

XML out

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <foo>text <it>italics</it> anything</foo>
    <tag>text <foo>
         <it>italics</it> stuff</foo>
   </tag>
</doc>

Upvotes: 1

Tom W
Tom W

Reputation: 5403

You haven't explained in what respect the solution you tried wasn't what you wanted, but it sounds like you've got the right idea. You can modify the identity template to remove the <copy> statement and it will then just loop through all elements depth-first, matching any of the desired element to your specific template. If that isn't what you want, please be more specific in your question.

Upvotes: 0

Related Questions