Ace
Ace

Reputation: 867

Changing file extensions within a XML file

This one is a bit of a tricky one. I have a contents.xml file that references a host of other files. These other files use to be .xml, and have been altered to .dita, my question is how can i renames all the .xml file extensions to .dita? The file paths are a varying levels in the tree and have an inconsistent number of subfolders in front of them.
Example:

<article
    xmlns:xi="http://www.w3.org/2001/XInclude">

   <title>Definition</title>
   <xi:include href="./introduction.xml"/>
   <section xml:id="viewComponents"><title>View Components</title>
      <xi:include href="./components/page.xml"/>
      <xi:include href="./views/sheet.xml"/>
      <xi:include href="./folder/xsubfolders/plaque.xml"/>
   </section>
</article>

To:

<article
    xmlns:xi="http://www.w3.org/2001/XInclude">

   <title>Definition</title>
   <xi:include href="./introduction.dita"/>
   <section xml:id="viewComponents"><title>View Components</title>
      <xi:include href="./components/page.dita"/>
      <xi:include href="./views/sheet.dita"/>
      <xi:include href="./folder/xsubfolders/plaque.dita"/>
   </section>
</article>

Upvotes: 2

Views: 1814

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243549

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xi="http://www.w3.org/2001/XInclude">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match=
   "xi:include/@href[substring(., string-length()-3)='.xml']">
  <xsl:attribute name="href">
    <xsl:value-of select="concat(substring(.,1, string-length()-3),'dita')"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<article
    xmlns:xi="http://www.w3.org/2001/XInclude">

   <title>Definition</title>
   <xi:include href="./introduction.xml"/>
   <section xml:id="viewComponents"><title>View Components</title>
      <xi:include href="./components/page.xml"/>
      <xi:include href="./views/sheet.xml"/>
      <xi:include href="./folder/xsubfolders/plaque.xml"/>
   </section>
</article>

produces the wanted, correct result:

<article xmlns:xi="http://www.w3.org/2001/XInclude">
    <title>Definition</title>
    <xi:include href="./introduction.dita"></xi:include>
    <section xml:id="viewComponents">
        <title>View Components</title>
        <xi:include href="./components/page.dita"></xi:include>
        <xi:include href="./views/sheet.dita"></xi:include>
        <xi:include href="./folder/xsubfolders/plaque.dita"></xi:include>
    </section>
</article>

Upvotes: 2

Robin
Robin

Reputation: 4260

You can do this with recursion:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">


    <xsl:template match="@*">
        <xsl:choose>
            <xsl:when test="substring(string(.), string-length(string(.)) - 3) = '.xml'">
                <xsl:attribute name="{name()}">
                    <xsl:value-of select="concat(substring(string(.), 1, string-length(string(.)) - 4), '.dita')"/>
                </xsl:attribute>
            </xsl:when>
            <xsl:otherwise>
                <xsl:attribute name="{name()}"><xsl:value-of select="string(.)"/></xsl:attribute>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

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

The template at the bottom copies all input directly to the output, with the exception of attributes which are picked up by the template above, and the text transform is applied here.

Upvotes: -1

Related Questions