How do I remove spaces in all attribute values using xslt?

24,294

Solution 1

You can use the translate function, like so, although it would make sense to refactor this with a call template:

<xsl:attribute name="OrderDate">
    <xsl:value-of select="translate(@OrderDate, ' ','')"/>
</xsl:attribute>
<xsl:attribute name="OrderNo">
    <xsl:value-of select="translate(@CustomertName, ' ','')"/>
</xsl:attribute>
<xsl:attribute name="CustomertName">
    <xsl:value-of select="translate(@CustomertName, ' ','')"/>
</xsl:attribute>

Solution 2

If you just want to removes spaces from the values of attributes, you could just create a template to match any attribute, and then use the translate function.

<xsl:template match="@*">
   <xsl:attribute name="{name()}">
      <xsl:value-of select="translate(., ' ', '')" />
   </xsl:attribute>
</xsl:template>

And if you want to filter out some attributes, you can create templates to match, and then ignore them. (XSLT will match the more specific template first)

<xsl:template match="Order/@OrderKey" />

You can also simplify you code somewhat by making use of the identity transform to cope existing nodes. Here is the full XSLT

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

   <xsl:template match="@*">
      <xsl:attribute name="{name()}">
         <xsl:value-of select="translate(., ' ', '')" />
      </xsl:attribute>
   </xsl:template>

   <xsl:template match="Order/@OrderKey" />

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

When applied to your sample XML, the following is ouptut

<OrderList>
  <Order OrderDate="26-July" OrderNo="ORDER12345" CustomertName="JOHNDOE">
    <ShipAddress AddressLine="ABCColony" FirstName="John" LastName="Doe"></ShipAddress>
  </Order>
</OrderList>

The advantage of this approach is that it will work with any XML document.

If you wanted to do this only for specific elements, try this XSLT instead which explicitly matches the attributes you want (and discards all others)

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

   <xsl:template match="Order/@OrderDate|Order/@OrderNo|Order/@CustomertName|ShipAddress/@AddressLine|ShipAddress/@FirstName|ShipAddress/@LastName">
      <xsl:attribute name="{name()}">
         <xsl:value-of select="translate(., ' ', '')"/>
      </xsl:attribute>
   </xsl:template>

   <xsl:template match="@*"/>

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

EDIT: If you wanted to remove only leading and trailing spaces, then 'normalize-space' is your friend.

<xsl:value-of select="normalize-space(.)" />

Do note this will remove excess spaces within the attribute though (that is to say double-spaces become single spaces between words).

Share:
24,294
SMA_JAVA
Author by

SMA_JAVA

Updated on February 23, 2020

Comments

  • SMA_JAVA
    SMA_JAVA over 4 years

    I want to remove spaces from all attributes in my xmls using xslt. I used strip-space, but that removes the spaces from nodes. My input xml is:

    <OrderList>
    <Order OrderDate="26-July" OrderNo="ORDER 12345"
     CustomertName="JOHN DOE" OrderKey="ORDKEY12345">
    <ShipAddress AddressLine="ABC Colony" FirstName="John" LastName="Doe "/>
    </Order>
    </OrderList>
    

    and the xsl I used to get rid of the spaces in the attributes like CustomertName="JOHN DOE" is:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*" />
    <xsl:template match="/">
    <xsl:apply-templates/>
    <OrderList>
        <xsl:for-each select="OrderList/Order">
            <xsl:element name="Order">
                <xsl:copy-of select="@OrderDate"/>
                <xsl:copy-of select="@OrderNo"/>
                <xsl:copy-of select="@CustomertName"/>
    
                <!-- ShipAddress begins -->
                <xsl:element name="ShipAddress">                                           
                    <xsl:copy-of select="ShipAddress/@AddressLine"/>
                    <xsl:copy-of select="ShipAddress/@FirstName"/>
                    <xsl:copy-of select="ShipAddress/@LastName"/>                       
                </xsl:element>
            </xsl:element>
        </xsl:for-each>             
    </OrderList>
    </xsl:template>
    </xsl:stylesheet> 
    

    But this leaves the input xml as it was. I want to remove the spaces from the attribute values at all levels.

  • SMA_JAVA
    SMA_JAVA almost 12 years
    Thanks a ton Tim, Also if I want to remove only leading and trainling whitespaces...what can i use then? Any help with this?
  • SMA_JAVA
    SMA_JAVA almost 12 years
    Hey thanks...but i was looking for something more generic...:)
  • StuartLC
    StuartLC almost 12 years
    @SMA_JAVA to strip just leading and trailing space, use normalize-space(@CustomertName)
  • Tim C
    Tim C almost 12 years
    I've edited my answer. normalize-space is the function you probably need!
  • SMA_JAVA
    SMA_JAVA almost 12 years
    Hey but one thing...I am also filtering out some attributes, if you see my xsl, OrderList\Order\@OrderKey was not there. But if i use your xsl, it will not filter out OrderKey, it will just copy all the attributes minus the leading and trailing spaces. Some more help with this please...
  • Tim C
    Tim C almost 12 years
    I've expanded the answer to show how you can exclude specific attributes
  • SMA_JAVA
    SMA_JAVA almost 12 years
    okk...so say i already have the xsl created which looks like the first xsl and i dont want to change it much apart from adding that bit to remove the leading and trailing whitespaces...for your code we are actually adding the attributes that require a removal, but my xsl only has the attributes which needs to be passed. When i use the whitespace removal bit along with my xsl, it gives the xml without whitespaces, but also with that appends the original input xml...and so it looks like...
  • SMA_JAVA
    SMA_JAVA almost 12 years
    <?xml version="1.0" encoding="UTF-16"?> <OrderList> <Order OrderDate="26-July" OrderNo="ORDER12345" CustomertName="JOHNDOE" OrderHeaderKey="ORDKEY12345"> <ShipAddress AddressLine="ABCColony" FirstName="John" LastName="Doe"></ShipAddress> </Order> </OrderList> <OrderList> <Order OrderDate="26-July" OrderNo="ORDER 12345" CustomertName="JOHN DOE"> <ShipAddress AddressLine="ABC Colony" FirstName="John" LastName="Doe " /> </Order> </OrderList>
  • Tim C
    Tim C almost 12 years
    I've added another XSLT sample to show how you would do it if you only wanted specific attributes.