When a XML
uses namespaces, they need to be declared and used in the .xsl
file so that the javax.xml.transform.Transformer
knows how to deal with various elements in the XML
. This post demonstrates how to deal with namespaces when performing transformation from or on XML
s.
Requirements
Stuff used in this post.
- Java 8 (JDK)
- Eclipse Mars.2 Release (4.5.2)
- Windows 10
- XSLT 1.0
Purpose
So we want to:
- Modify elements that use prefixes from different namespaces
- Conditional modify attributes and retaining their prefixes, if any.
- Conditional modify elements based on their values (i.e., from text())
We’ll use files
- input.xml
- The file whose content is to be modified and written out to output.xml
- transformation.xsl
- Contains XSL expressions to modify certain data
- output.xml
- The output file
Input XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?xml version="1.0" encoding="UTF-8"?> <CATALOG xmlns="https://turreta.com/blog/default-ns" xmlns:artist="https://turreta.com/blog/artist-ns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://arvato-systems.de/csdb-si csdb-si-messages.xsd "> <CD> <TITLE>Empire Burlesque</TITLE> <artist:ARTIST>Bob Dylan</artist:ARTIST> <COUNTRY>USA</COUNTRY> <COMPANY>Columbia</COMPANY> <PRICE xsi:type="WholeSalePrice">10.90</PRICE> <YEAR>1985</YEAR> </CD> <CD> <TITLE>Hide your heart</TITLE> <artist:ARTIST>Bonnie Tyler</artist:ARTIST> <COUNTRY>UK</COUNTRY> <COMPANY>CBS Records</COMPANY> <PRICE xsi:type="RetailSalePrice">9.90</PRICE> <YEAR>1988</YEAR> </CD> </CATALOG> |
Our Java Codes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package com.turreta.xml.xlst.nsdemo; import java.io.File; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; public class NSDemo { public static void main(String[] args) { ClassLoader classLoader = NSDemo.class.getClassLoader(); // Read from /resources folder Source inputXml = new StreamSource(classLoader.getResource("input.xml").getFile()); // Read from /resources folder Source xsl = new StreamSource(classLoader.getResource("transformation.xsl").getFile()); Result outputXml = new StreamResult( new File("C:\\Users\\user123\\Desktop\\test-data\\output.xml")); try { Transformer transformer = TransformerFactory.newInstance().newTransformer(xsl); transformer.transform(inputXml, outputXml); } catch (TransformerException e) { e.getMessage(); } } } |
XSL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:default="https://turreta.com/blog/default-ns" xmlns:artist="https://turreta.com/blog/artist-ns" xmlns:my-artist="https://turreta.com/blog/artist-ns" xmlns:my-xsi="http://www.w3.org/2001/XMLSchema-instance"> <xsl:output method="xml" indent="yes"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="/default:CATALOG/default:CD/default:TITLE"> <xsl:copy> <xsl:value-of select="translate(text(), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" /> </xsl:copy> </xsl:template> <!-- Changes all 'type' attribute in /CATALOG/CD/PRICE <xsl:template match="/default:CATALOG/default:CD/default:PRICE/@my-xsi:type"> <xsl:attribute name='xsi:type'>This is the value</xsl:attribute> </xsl:template> --> <xsl:template match="/default:CATALOG/default:CD/default:PRICE[@my-xsi:type='WholeSalePrice']/@my-xsi:type"> <xsl:attribute name='xsi:type'>whole-sale-price</xsl:attribute> </xsl:template> <xsl:template match="/default:CATALOG/default:CD/default:PRICE[@my-xsi:type='RetailSalePrice']/@my-xsi:type"> <xsl:attribute name='xsi:type'>retail-sale-price</xsl:attribute> </xsl:template> <xsl:template match="/default:CATALOG/default:CD/artist:ARTIST[text()='Bob Dylan']"> <xsl:copy> <xsl:value-of select="translate(text(), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" /> </xsl:copy> </xsl:template> </xsl:stylesheet> |
The Transformation
Change TITLE string value to upper-case string value
The expression below replaces all TITLE string value to upper-case string value. “Empire Burlesque” is changed to “EMPIRE BURLESQUE”.
1 2 3 4 5 6 7 | ... <xsl:template match="/default:CATALOG/default:CD/default:TITLE"> <xsl:copy> <xsl:value-of select="translate(text(), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" /> </xsl:copy> </xsl:template> ... |
Change PRICE’s type attribute value conditionally
If type is “WholeSalePrice”, replace it with “whole-sale-price” and retaining the attribute’s prefix.
1 2 3 4 5 | ... <xsl:template match="/default:CATALOG/default:CD/default:PRICE[@my-xsi:type='WholeSalePrice']/@my-xsi:type"> <xsl:attribute name='xsi:type'>whole-sale-price</xsl:attribute> </xsl:template> ... |
If type is “RetailSalePrice”, replace it with “retail-sale-price” and retaining the attributes’ prefix.
1 2 3 4 5 | ... <xsl:template match="/default:CATALOG/default:CD/default:PRICE[@my-xsi:type='RetailSalePrice']/@my-xsi:type"> <xsl:attribute name='xsi:type'>retail-sale-price</xsl:attribute> </xsl:template> ... |
Change only “Bob Dylan” to “BOB DYLAN”
1 2 3 4 5 6 7 | ... <xsl:template match="/default:CATALOG/default:CD/artist:ARTIST[text()='Bob Dylan']"> <xsl:copy> <xsl:value-of select="translate(text(), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" /> </xsl:copy> </xsl:template> ... |
Download the Codes
https://github.com/Turreta/Java-XSLT-and-XML-with-Namespaces