I am trying to replace namespace string using xslt.
I have the source namespace string and target namespace string in another xml file in the format of "namespace source="xxx" target="xxx"". All source namespace strings in my to-be-transformed xml should be changed to the corresponding target value. Only elements need to be considered as attributes don't have namespace.
I'm using the JDK default xalan xslt processor, which supports xslt 1.0. I'd like to stick to xslt 1.0 if possible, but I can change processor and use xslt 2.0 if really needed.
For example, to-be-transformed input xml:
<root xmlns="http://ns1" xmlns:ns2="http://ns2-old" xmlns:ns3="http://ns3">
<ElementA xmlns="http://ns4-old">
<ElementB/>
<ns2:elementD/>
</ElementA>
</root>
The output xml should be ("http://ns2-old" is changed to "http://ns2-new", and "http://ns4-old" is changed to "http://ns4-new"):
<root xmlns="http://ns1" xmlns:ns2="http://ns2-new" xmlns:ns3="http://ns3">
<ElementA xmlns="http://ns4-new">
<ElementB/>
<ns2:elementD/>
</ElementA>
</root>
Here is my xsl that is not working:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="nsmapdoc" select="document('my-map-file')"/>
<xsl:key name="nsmap" match="//namespace/#target" use="#source"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- process each element -->
<xsl:template match="element()">
<xsl:for-each select="namespace::*">
<!-- for each namespace node of the element, save the string value-->
<xsl:variable name="sourceuri"><xsl:value-of select="."/>
</xsl:variable>
<!-- get the target value for this namespace-->
<xsl:variable name="targeturi">
<xsl:for-each select="$nsmapdoc">
<xsl:value-of select="key('nsmap', $sourceuri)"/>
</xsl:for-each>
</xsl:variable>
<!-- if target value exists, replace the current namespace node string value with the target value-->
<xsl:if test="$targeturi">
<xsl:value-of select="$targeturi"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I have a few questions:
For the identity template that do the copy, why doing "match="node()|#*" instead of just "match="node()"? Is attribute also a node?
I am not sure if I did correctly to get the namespace string value (like "http://ns1", "http://ns2-old") for the element.
I think I got the key correctly. However, I am not sure if I used the type correctly---looks like targeturi variable is not a string. If key does not have the entry, what will lookup the entry return? In my case, I should replace the namespace value only for the namespace that has an entry in the map.
How to write a new string value for the namespace node?
I need to process each namespace nodes for the element. Is it the right way to define a variable inside ?
please help to see what is wrong with my xsl. Any suggestion is appreciated.
I think you have two, possibly three, separate questions here.
The first question is: how to move elements from one namespace to another, using a "map" of source-to-target namespaces. Let me answer this question first. Given:
XML
<root xmlns="http://ns1" xmlns:ns2="http://ns2-old" xmlns:ns3="http://ns3">
<ElementA xmlns="http://ns4-old">
<ElementB/>
<ns2:ElementD/>
</ElementA>
</root>
map.xml
<root>
<namespace source="http://ns2-old" target="http://ns2-new"/>
<namespace source="http://ns4-old" target="http://ns4-new"/>
</root>
The following stylesheet:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:param name="nsmapdoc" select="document('map.xml')"/>
<xsl:template match="*">
<xsl:variable name="old-ns" select="namespace-uri()"/>
<xsl:variable name="map-entry" select="$nsmapdoc/root/namespace[#source=$old-ns]"/>
<xsl:variable name="new-ns">
<xsl:choose>
<xsl:when test="$map-entry">
<xsl:value-of select="$map-entry/#target"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$old-ns"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{local-name()}" namespace="{$new-ns}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
will return:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="http://ns1">
<ElementA xmlns="http://ns4-new">
<ElementB/>
<ElementD xmlns="http://ns2-new"/>
</ElementA>
</root>
Note:
ElementA and its child ElementB have been moved from namespace URI "http://ns4-old" to URI "http://ns4-new";
ElementD has been moved from namespace URI "http://ns2-old" to URI "http://ns2-new";
The prefix of ElementD has been stripped off; this is a meaningless, cosmetic change, and it should not present any problems for the receiving application;
The root element has remained in its original namespace;
Unused namespace declarations have been discarded.
Note also that we are not using a key to lookup the new namespace: using a key across documents is quite awkward in XSLT 1.0 and I have chosen to do without.
The second question is how to copy the unused namespace declarations. There are several possible answers to choose from:
It's not necessary to copy them, since that are not used for anything;
It's not possible to copy them;
It is possible to copy them by copying some element from the source document; however copying an element also copies its namespace - so this can be done only if there is a known element that is supposed to stay in its original namespace. For example, if you know beforehand that the root element is not supposed to be moved to another namespace, you can add another template to the stylesheet:
to get this result:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="http://ns1" xmlns:ns2="http://ns2-old" xmlns:ns3="http://ns3">
<ElementA xmlns="http://ns4-new">
<ElementB/>
<ElementD xmlns="http://ns2-new"/>
</ElementA>
</root>
Related
My First question is marked as duplicated, but it isn't a duplicate
show XML in HTML with inline stylesheet
I hope this question is not immediatley marked as duplicate, only because one of the moderators has read the first two sentences and've ignored the rest.
The Problem is not to show an XML Structure in HTML, rather to show a full dynamically XML structure, with all tags and occasional colored lines.
The structure and interior fields are full dynamically and every field can be correct or wrong, depending on the xml file like to compare.
So a field is at the first comparison correct, but on another comparison it’s wrong. The fields and structure of XML can vary greatly from one comparison to another.
I’m looking since yesterday for a corresponding and professional solution for this problem.
Background process: comparison different xml files, via soa microservices in java. The comparison is made by org.custommonkey.xmlunit. The Result have to be an html popup, what shows me differences marked by colored lines.
Example Output XUnit Diff Result XPath
/ROOT[1]/MATDETAIL[1]/OUTPUT[1]/GENERAL[1]/CHANGED_BY[1]/text()[1]
Transform the source xml via xslt and the xunit diff result informations.
Example Input XML
<ROOT>
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<CHANGED_BY>NEW USER</CHANGED_BY>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
Example XSL Transformation
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" mode="unescape"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ROOT[1]/MATDETAIL[1]/OUTPUT[1]/GENERAL[1]/CHANGED_BY[1]">
<xsl:element name = "span">
<xsl:attribute name="style">font-weight:bold; color:red </xsl:attribute>
<xsl:copy>
<xsl:value-of select = "current()" />
</xsl:copy>
<xsl:text><== Expected: dasda</xsl:text>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Example Result of XSL Transformation
<ROOT>
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<span style="font-weight:bold; color:red "><CHANGED_BY>NEW USER</CHANGED_BY><== Expected: ORIGINAL USER</span>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
I’m not able to show this xml structure in html, with (all) tags, correctly AND colored.
Either I’ve get no tags, so there are only the raw data in XML to see, without tags, but the lines are colored.
Or I get the xml structure with all data, but not colored.
I tried to replace the lt and gt chars inside xslt, but failed, or after transformation in java, this result shows very ugly. My colleague has meant that we can not use it in any way.
Because the XML Structur can be every time different and so on fully dynamically, I can not style the xml with css and tag definition.
Unfortunately, alternative implementations are not an option. I have to do this somehow with the means available to me. (Java, XML & XSL, JS, HTML, CSS).
I hope to get good ideas to solute this.
I would like to thank you in advance.
I hope i can solve your issue with following try.
I. Input:
<ROOT baum="baum">
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<CHANGED_BY>NEW USER</CHANGED_BY>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
II. Stylesheet (XSLT 1.0):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="CHANGED_BY">
<span style="color:red;">
<xsl:apply-templates select="." mode="serialize"/>
</span>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates select="." mode="serialize"/>
</xsl:template>
<xsl:template match="#*">
<xsl:apply-templates select="." mode="serialize"/>
</xsl:template>
<xsl:template match="*" mode="serialize">
<xsl:value-of select="concat('<', name())"/>
<xsl:apply-templates select="#*" />
<xsl:choose>
<xsl:when test="node()">
<xsl:text>></xsl:text>
<xsl:apply-templates />
<xsl:value-of select="concat('<', name(), '>')"/>
</xsl:when>
<xsl:otherwise>
<xsl:text> /></xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="#*" mode="serialize">
<xsl:value-of select="concat(' ', name(), '="', ., '"')"/>
</xsl:template>
<xsl:template match="text()" mode="serialize">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
III: Output:
<ROOT baum="baum">
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON />
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE />
<span style="color:red;"><CHANGED_BY>NEW USER</CHANGED_BY></span>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE />
<LOG_NO />
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
IV. Explanation:
Whenever the mode="serialize" is applied, the context is escaped. See example for CHANGED_BY to format with HTML-Tags. The xml structure is fully escaped so the browser shows it like a string instead of tags.
I really hope it solves your problem
I have a number of Java classes that I am using in conjunction with JAXB in order to generate XML. The java classes have minimal changes from year to year but the output XML needs to have very specific yearly changes to it and it's proving a little elusive. I've tried updating the attributes using DOM but nodes further along the tree are maintaining the previous state. I've tried using reflection to update the annotations directly before marshalling but it doesn't seem to be having the desired effect. I've also tried replacing the XMLRootElement object (and XMLType, XMLElement) with local classes but nothing seems to be working properly as some information always seems to be retained somewhere even when it seems that I have changed the member/attribute/etc.
I am not going to duplicate all the java objects on a yearly basis just so that I can change the namespaces to match the requirements.
Right now I'm at the point where I think XSLT might be the last option but I have little to no knowledge of it. Is there a simple way to update 5-8 namespace URI's that are located on the root element? I don't want to change the prefixes (they are already set using a prefix mapper), I just want to change the namespace from "com.help.me.2014" to "com.help.me.2015".
Thanks
Andy
Resolution:
First off I greatly appreciate the effort and responses. I didn't actually try any of them as I came up with a different solution prior to getting back to see them.
Anyone coming along in the future can try the items listed below (as an XSLT solution) or you can try what I describe below.
I am generating XML in two different styles/formats, one with and one without SOAP wrappers. Due to my difficulty accessing the actual namespaces within the DOM/SOAP objects and my inability to alter the annotations at runtime I ended up capturing the output stream and manipulating the resulting string.
SOAP:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
soapMessage.writeTo(stream);
String file = new String(stream.toByteArray);
... manipulate file (now a string), replace values, etc. -> actually passed to dependency injected converters, then send on to client via response.write
JAXB Marshalling is very similar to the SOAP, both send the resulting String onto converters which manipulate it as a StringBuilder then send it on.
Thanks again for the suggestions. Hopefully it helps someone in the future although the requirement is a little out there.
Andy
Changing namespaces every year is almost certainly the wrong thing to do, but the following XSLT stylesheet will change namespaces
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:old="oldspace"
version="1.0">
<xsl:template match="old:*">
<xsl:element name="{local-name(.)}" namespace="newspace">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#old:*">
<xsl:attribute name="{local-name()}" namespace="newspace">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="*">
<xsl:copy select=".">
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="processing-instruction()|comment()">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
This style sheet creates a copy of every element changing the namespace from oldspace to newspace when appropriate. Other than the namespace change, the original document is preserved. Similar templates can be made for every namespace that needs to be changed (note there are two templates that are namespace specific).
Note that prefixes WILL be altered. These are not really content as such, so it is nearly impossible to preserve them in a case like this. The only way I can think of to preserve those would involve writing a separate template for each element in the original, directly creating the new elements instead of using the xsl:element element.
For example, the given xml
<os:myroot xmlns:os="oldspace">
<?keep-this?>
<os:testing abc='3' def='9'>
<!-- This is a child -->
<os:item>1234</os:item>
</os:testing>
<!-- this element is in the default namespace -->
<testing2>
<abc>112233</abc>
</testing2>
</os:myroot>
is transformed to
<myroot xmlns="newspace">
<?keep-this?>
<testing>
<!-- This is a child -->
<item>1234</item>
</testing>
<!-- this element is in the default namespace -->
<testing2 xmlns="">
<abc>112233</abc>
</testing2>
</myroot>
where all elements that were in the oldspace namespace are now in the newspace namespace.
Here's an option that allows you to pass the old and new namespace URIs in as xsl:params.
XML Input (Borrowed from Matthew's answer; thanks!)
<os:myroot xmlns:os="com.help.me.2014">
<?keep-this?>
<os:testing abc='3' def='9'>
<!-- This is a child -->
<os:item>1234</os:item>
</os:testing>
<!-- this element is in the default namespace -->
<testing2>
<abc>112233</abc>
</testing2>
</os:myroot>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="oldns" select="'com.help.me.2014'"/>
<xsl:param name="newns" select="'com.help.me.2015'"/>
<xsl:template match="#*|node()" name="ident">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" priority="1">
<xsl:choose>
<xsl:when test="namespace-uri()=$oldns">
<xsl:element name="{name()}" namespace="{$newns}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
XML Output
<os:myroot xmlns:os="com.help.me.2015"><?keep-this?>
<os:testing abc="3" def="9"><!-- This is a child -->
<os:item>1234</os:item>
</os:testing><!-- this element is in the default namespace -->
<testing2>
<abc>112233</abc>
</testing2>
</os:myroot>
Here's an XSLT 2.0 option that produces the same output...
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="oldns" select="'com.help.me.2014'"/>
<xsl:param name="newns" select="'com.help.me.2015'"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" priority="1">
<xsl:element name="{name()}" namespace="{
if (namespace-uri()=$oldns) then $newns else namespace-uri()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Here's another 2.0 example that handles multiple namespace uris. The old and new uris are passed in as a string with commas as delimiters.
The order of the uris are important. The first old uri corresponds to the first new uri. The second old uri corresponds to the second new uri. Etc.
XML Input (updated to have more than one namespace uri)
<os:myroot xmlns:os="com.help.me.2014">
<?keep-this?>
<os:testing abc='3' def='9'>
<!-- This is a child -->
<os:item>1234</os:item>
</os:testing>
<!-- this element is in the default namespace -->
<testing2>
<abc>112233</abc>
</testing2>
<os2:testing xmlns:os2="com.help.me.again.2014">
<os2:item>ABCD</os2:item>
</os2:testing>
</os:myroot>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="oldns" select="'com.help.me.2014,com.help.me.again.2014'"/>
<xsl:param name="newns" select="'com.help.me.2015,com.help.me.again.2015'"/>
<xsl:variable name="oldns-seq" select="tokenize($oldns,',')"/>
<xsl:variable name="newns-seq" select="tokenize($newns,',')"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" priority="1">
<xsl:variable name="nsIdx" select="index-of($oldns-seq,namespace-uri())"/>
<xsl:element name="{name()}" namespace="{
if (namespace-uri()=$oldns-seq) then $newns-seq[$nsIdx] else namespace-uri()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
XML Output
<os:myroot xmlns:os="com.help.me.2015"><?keep-this?>
<os:testing abc="3" def="9"><!-- This is a child -->
<os:item>1234</os:item>
</os:testing>
<!-- this element is in the default namespace -->
<testing2>
<abc>112233</abc>
</testing2>
<os2:testing xmlns:os2="com.help.me.again.2015">
<os2:item>ABCD</os2:item>
</os2:testing>
</os:myroot>
I have a xml file whose structure looks like this:
<root>
<includes>
<includeFile name="../other/some_xml.xml"/>
</includes>
<itemlist>
<item id="1" >
<selections>
<selection name="one" />
</selections>
</item>
</itemlist>
The xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml" indent="yes" xalan:indent-amount="4" />
<xsl:template match="/">
<xsl:element name="ItemList">
<xsl:if test="root/item">
<xsl:call-template name="templ" />
</xsl:if>
</xsl:element>
</xsl:template>
<xsl:template name="templ">
<xsl:element name="ItemList">
<xsl:for-each select="root/itemlist/item">
<xsl:element name="Item">
<xsl:element name="ItemIdentifier">
<xsl:value-of select="#id" />
</xsl:element>
<xsl:element name="Condition">
<xsl:value-of select="selections/selection[1]/#name" />
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I created one XSLT which i am using to filter out items. The problem is that for every file, i have to check if it contains the includefile tag, which is a relative path pointing to a similar xml, and if it does, i need to collect items from that file also, recursively. For now i transformed the xml using my xslt and then i have to parse the xml to look for includefile tag. This solution doesn't look elegant and i was wondering if all of it could be done via xslt.
The XSLT document function in XSLT 1.0 and in XSLT 2.0 additionally the doc function allow you to pull in further documents, processing is then simply possible with matching templates. So consider to move your XSLT coding style to write matching templates and apply-templates, then you can easily do
<xsl:template match="includes/includeFile">
<xsl:apply-templates select="document(#name)/*"/>
<xsl:template>
and then you simply need to make sure the <xsl:template match="root">...</xsl:template> creates the output you want.
I have an input XML file which looks like this:
<Root>
<Monday>Monday<Monday>
<Indicator>true<Indicator>
<Value>1<Value>
<Tuesday>Tuesday<Tuesday>
<Indicator>true<Indicator>
<Value>2<Value>
<Wednesday>Wednesday<Wednesday>
<Indicator>true<Indicator>
<Value>3<Value>
</Root>
It must be converted to the output XML file which is:
<Root>
<Monday>Monday<Monday>
<Value>1<Value>
<Tuesday>Tuesday<Tuesday>
<Value>2<Value>
<Wednesday>Wednesday<Wednesday>
<Value>3<Value>
</Root>
The problem is that the input XML can vary. Sometimes it might be
<Root>
<Monday>Monday<Monday>
<Indicator>true<Indicator>
<Value>1<Value>
<Thursday>Thursday<Thursday>
<Indicator>true<Indicator>
<Value>4<Value>
</Root>
Now the output must be
<Root>
<Monday>Monday<Monday>
<Value>1<Value>
<Thursday>Thursday<Thursday>
<Value>4<Value>
</Root>
I also have the list of valid tags like Monday, Tuesday etc, which can come in the input XML in an ArrayList in Java. Any ideas on how to accomplish this?
From this answer: How to remove elements from xml using xslt with stylesheet and xsltproc? :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Indicator"/>
</xsl:stylesheet>
I want to convert XML to XML using XSLT in JAVA. How to add namespace name and it's value in XSLT file? I have tried many ways to get the namespace value but didn't get the output what i expect. So Please do the needful.
This is my XML,
<?xml version="1.0" encoding="ISO-8859-1"?>
<root xmlns="namespacename">
<child>A</child>
<child>B</child>
</root>
XSLT file,
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:element name="root" namespace="namespacename">
<xsl:element name="child-one">
<xsl:value-of select="root/child"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I need the output XML file like this.
<?xml version="1.0" encoding="ISO-8859-1"?>
<root xmlns="namespacename">
<child-one>A</child-one>
</root>
If you know the namespace, then simply add it as the default namespace and write the result as literal elements.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="namespacename"
xmlns:i="namespacename"
exclude-result-prefixes="i">
<xsl:template match="/">
<root>
<child-one>
<xsl:value-of select="i:root/i:child"/>
</child-one>
</root>
</xsl:template>
</xsl:stylesheet>
Note that the XPath expression root/child normally doesn't respect the default namespace, so you have to declare an additional namespace with a prefix (e.g. i) so the path becomes i:root/i:child. However, this also requires excluding the namespace for the result using exclude-result-prefixes="i".