Search code examples
xmlxsltrssxslt-1.0

Lowercase all tag names and attributes inside RSS XML using XSLT


How can I please turn the below (capital letter tags i.e. <RSS> and capital letter attributes i.e. TYPE="audio/mpeg")

<RSS xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
    <CHANNEL>
        <title>Example Title</title>
        <LINK>Example Link</link>
        <atom:link HREF="http://example.com/feed" REL="self" TYPE="application/rss+xml"/>
        <itunes:subtitle>Example subtitle with itunes namespace</itunes:subtitle>
        <itunes:owner>
            <itunes:name>OWNER NAME</itunes:name>
            <itunes:email>owner@gmail.com</itunes:email>
        </itunes:owner>
        <ITEM>
            <TITLE>Title Name here</TITLE>
            <itunes:author>Author name here</itunes:author>
            <ENCLOSURE TYPE="audio/mpeg" URL="http://www.podtrac.com/abc.mp3" LENGTH="31805"/>
        </ITEM>
    </CHANNEL>
</RSS>

Into this (lower case letter tags i.e. <rss> and lower case letter attributes i.e. type="audio/mpeg")

<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
    <channel>
        <title>Example Title</title>
        <link>Example Link</link>
        <atom:link href="http://example.com/feed" rel="self" type="application/rss+xml"/>
        <itunes:subtitle>Example subtitle with itunes namespace</itunes:subtitle>
        <itunes:owner>
            <itunes:name>OWNER NAME</itunes:name>
            <itunes:email>owner@gmail.com</itunes:email>
        </itunes:owner>
        <item>
            <title>Title Name here</title>
            <itunes:author>Author name here</itunes:author>
            <enclosure TYPE="audio/mpeg" url="http://www.podtrac.com/abc.mp3" length="31805"/>
        </item>
    </channel>
</rss>

Using XSLT?

NOTES:

  1. Needs to be all tags and all attributes that are lowercased, not just my example ones of <RSS> to <rss>, and TYPE="audio/mpeg" to type="audio/mpeg"
  2. I will be using PHP to run this
  3. Please notice the line one namespace setup of xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" inside the <rss> tag -- this must remain
  4. Please notice the iTunes namespace items such as <itunes:name>OWNER NAME</itunes:name> - these must remain exactly the same

Solution

  • This gives the desired result in XSLT-1.0:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
        <xsl:output indent="yes" />
        <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
        <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
    
        <!-- lowercase'es all elements names and copies namespaces-->
        <xsl:template match="*">
            <xsl:variable name="rawName" select="substring-before(name(), ':')"/>
            <xsl:element name="{translate(name(), $uppercase, $smallcase)}" namespace="{namespace-uri()}">
                <xsl:copy-of select="namespace::*"/>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:element>
        </xsl:template>
    
        <!-- lowercase'es all attribute names -->
        <xsl:template match="@*">
            <xsl:attribute name="{translate(name(), $uppercase, $smallcase)}">
              <xsl:value-of select="." />
            </xsl:attribute>
        </xsl:template>
    
        <!-- copies the rest -->
        <xsl:template match="text() | comment() | processing-instruction()">
            <xsl:copy/>
        </xsl:template>
    
    </xsl:stylesheet>