I have a xml structure "Filter" that get unmarshalled into in a java class called "Filter".
The XML state looks roughly like:
<filter>
<propertyType>
<propertyName>prop1</propertyName>
<propertyValue>val1</propertyValue>
</propertyType>
<propertyType>
<propertyName>prop2</propertyName>
<propertyValue>val2</propertyValue>
</propertyType>
</filter>
Ordinarily, it works great.
However, there are certain situations where one of these property values itself contains xml structure (see second propertyValue below):
<filter>
<propertyType>
<propertyName>prop1</propertyName>
<propertyValue>val1</propertyValue>
</propertyType>
<propertyType>
<propertyName>prop2</propertyName>
<propertyValue><nodeA><nodeB>valB</nodeB></nodeA></propertyValue>
</propertyType>
</filter>
The problem here is that after unmarshalling this structure, the propertyValue is null.
I would like to simply be able to have the unmarshalling ignore this xml-looking code and treat it as a simple string value.
Does anyone know how I can accomplish this? Thanks for any reply!
How about the annotation of using "#XmlAnyElement"?
You can get the instance of org.w3c.dom.Element.
The text data should be able to be obtained by operating this instance.
class PropertyType {
private String propertyName;
// private String propertyValue; // comment out
#XmlAnyElement(lax=true)
private List<org.w3c.dom.Element> propertyValue; // Adding this
}
exsample of to get text data.
// It is assumed that the child node is one.
org.w3c.dom.Node nd = propertyValue.get(0).getFirstChild();
while(true) {
if (nd.hasChildNodes()) {
nd = nd.getFirstChild();
} else {
System.out.println(nd.getNodeValue()); // this is text data
break;
}
}
For this use case I would create an XSLT that will convert the XML document. Then using the javax.xml.transform.* APIs, transform the XML to a JAXBResult to unmarshal the object:
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.util.JAXBResult;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
File xsltFile = new File("transform.xsl");
StreamSource xsltSource = new StreamSource(xsltFile);
Transformer transformer = tf.newTransformer(xsltSource);
File xml = new File("input.xml");
StreamSource xmlSource = new StreamSource(xml);
JAXBContext jc = JAXBContext.newInstance(Filter.class);
JAXBResult jaxbResult = new JAXBResult(jc);
transformer.transform(xmlSource, jaxbResult);
Filter filter = (Filter) jaxbResult.getResult();
}
}
transform.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<xsl:template match="propertyValue"> <xsl:value-of select="descendents"/>
<xsl:element name="propertyValue">
<xsl:value-of select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
AFAIK the JAXB work on xml schema for unmarshalling XML into Java object. So if schema defines element as simple element, it can only contain text. If you need to store XML as simple text. You might need to escape it using CDATA construct. Try enclosing the same as shown below, after unmarshling you will get the XML as it is.
<filter>
<propertyType>
<propertyName>prop1</propertyName>
<propertyValue>val1</propertyValue>
</propertyType>
<propertyType>
<propertyName>prop2</propertyName>
<propertyValue><![CDATA[<nodeA><nodeB>valB</nodeB></nodeA>]]></propertyValue>
</propertyType>
</filter>
Related
I am not able to display the value of xml tag using namespace - tag with colon.
When there are no colons in tags, code works perfectly, but as soon I want to display a tag which contains colon, program doesnt throw any error, only doesn`t show any value.
Here is the XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:inv="http://www.w3schools.com/daco" xmlns:lst="http://www.esa.int/safe/sentinel-1.0" version="1.0">
<lst:howto>
<topic id="1">
<nieco>
<lst:title>Java</lst:title>
</nieco>
</topic>
</lst:howto>
</xsl:stylesheet>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:lst="http://www.esa.int/safe/sentinel-1.0" version="1.0">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/">
topic
<xsl:for-each select="//nieco">
<xsl:value-of select="lst:title" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
and Java:
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
class XMLtoCsVConversion2 {
public static void main(String args[]) throws Exception {
File stylesheet = new File("C:/java/howto.xsl");
File xmlSource = new File("C:/java/howto.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlSource);
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(stylesource);
Source source = new DOMSource(document);
Result outputTarget = new StreamResult(new File("xyz.csv"));
transformer.transform(source, outputTarget);
System.out.println("done");
}
}
Codes really simplified to find the cause of the problem, but I was not able to figure it out.
If I would remove lst: from tag in xml and from xsl, it would work, as soon there is colon, program doesn`t show any value.
But XML we receive contain plenty of tags with colon, so I would a solution to this problem.
Please if you have any idea where could be the problem, please let me know :)
Expected output:
topic
Java
Try this;
public static void main(String args[]) throws Exception {
File stylesheet = new File("C:/java/howto.xsl");
File xmlSource = new File("C:/java/howto.xml");
// DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// DocumentBuilder builder = factory.newDocumentBuilder();
// Document document = builder.parse(xmlSource);
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(stylesource);
//Source source = new DOMSource(document);
Source source = new StreamSource(xmlSource);
Result outputTarget = new StreamResult(new File("C:/java/xyz.csv"));
transformer.transform(source, outputTarget);
System.out.println("done");
}
PROBLEM
I am working on a problem where I am required to take JSON input file and convert to a XML file. I have provided an example below of what i am deaing with.
In JSON :
"playerStats": [
{ "jerseyNumber": "23", "fgPercentage": 60, "plusMinus": "plus" },
{ "jerseyNumber": "24", "fgPercentage": 40, "plusMinus": "minus" }
] }
In XML :
<BallerStats>
<BallerStat>
<Baller><BallerJersey>23</BallerJersey><Type>Jersey</Type></Baller>
<fgPercentage><Type>PERCENT</Type><Value>60</Value></fgPercentage>
</BallerStat>
<BallerStat>
<Baller><BallerJersey>23</BallerJersey><Type>Jersey</Type></Baller>
<fgPercentage><Type>PERCENT</Type><Value>60</Value></fgPercentage>
</BallerStat>
</BallerStats>
As you can see it is not a 1 to 1 ratio meaning, in JSON we represent fgPercentage as 60 but in xml we separate it by "value" and "type"
Also certain tag names are different. In JSON we call them "playerStats" and in XML we call the equivalent tag "BallerStats"
SOLUTION
Keep in mind the JSON file could have many other fields apart from playerstats like coachstats or fanstats but we only care about playerstats
The following is what I have come up with but again I could be wrong.
Scan Json and look for "playerStats"
If not found , Do nothing.
If found then grab valuable information like jerseyNumber , fgPercentage, ignore plusMinus and store them in a object of a template class with these Values.
Then use the Object to generate appropriate XML tags.
I am not sure if my approach is effective or efficient. I would love to hear suggestions and I am doing this in Java so feel free to refer to any reliable and popular libraries. I would love to see all approaches and even better if you provide code snippet.
One option is to use json-to-xml() in XSLT 3.0.
You'll need an XSLT 3.0 processor; I used Saxon-HE 9.8 in my example below.
You can pass the JSON in as a param.
The results of json-to-xml() will look something like this:
<map xmlns="http://www.w3.org/2005/xpath-functions">
<array key="playerStats">
<map>
<string key="jerseyNumber">23</string>
<number key="fgPercentage">60</number>
<string key="plusMinus">plus</string>
</map>
<map>
<string key="jerseyNumber">24</string>
<number key="fgPercentage">40</number>
<string key="plusMinus">minus</string>
</map>
</array>
</map>
You can process that XML to get your target XML.
Example...
Java
package so.test1;
import java.io.File;
import java.io.OutputStream;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.XsltTransformer;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
import net.sf.saxon.s9api.XdmAtomicValue;
import net.sf.saxon.s9api.XsltCompiler;
import net.sf.saxon.s9api.XsltExecutable;
/**
*
* #author dhaley
*
*/
public class SOTest1 {
public static void main(String[] args) throws SaxonApiException {
final String XSLT_PATH = "src/so/test1/test.xsl";
final String JSON = "{\"playerStats\": [\n" +
" {\"jerseyNumber\": \"23\", \"fgPercentage\": 60, \"plusMinus\": \"plus\"},\n" +
" {\"jerseyNumber\": \"24\", \"fgPercentage\": 40, \"plusMinus\": \"minus\"}\n" +
"]}";
OutputStream outputStream = System.out;
Processor processor = new Processor(false);
Serializer serializer = processor.newSerializer();
serializer.setOutputStream(outputStream);
XsltCompiler compiler = processor.newXsltCompiler();
XsltExecutable executable = compiler.compile(new StreamSource(new File(XSLT_PATH)));
XsltTransformer transformer = executable.load();
transformer.setInitialTemplate(new QName("init")); //<-- SET INITIAL TEMPLATE
transformer.setParameter(new QName("json"), new XdmAtomicValue(JSON)); //<-- PASS JSON IN AS PARAM
transformer.setDestination(serializer);
transformer.transform();
}
}
XSLT 3.0 (test.xsl)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.w3.org/2005/xpath-functions">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="json"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template name="init">
<!--Only process playerStats-->
<xsl:apply-templates select="json-to-xml($json)//array[#key='playerStats']"/>
</xsl:template>
<xsl:template match="array">
<BallerStats>
<xsl:apply-templates/>
</BallerStats>
</xsl:template>
<xsl:template match="map">
<BallerStat>
<xsl:apply-templates/>
</BallerStat>
</xsl:template>
<xsl:template match="*[#key='jerseyNumber']">
<Baller>
<BallerJersey xsl:expand-text="true">{.}</BallerJersey>
<Type>Jersey</Type>
</Baller>
</xsl:template>
<xsl:template match="*[#key='fgPercentage']">
<fgPercentage>
<Type>PERCENT</Type>
<Value xsl:expand-text="true">{.}</Value>
</fgPercentage>
</xsl:template>
<xsl:template match="*[#key=('plusMinus')]"/>
</xsl:stylesheet>
Output (stdout)
<?xml version="1.0" encoding="UTF-8"?>
<BallerStats>
<BallerStat>
<Baller>
<BallerJersey>23</BallerJersey>
<Type>Jersey</Type>
</Baller>
<fgPercentage>
<Type>PERCENT</Type>
<Value>60</Value>
</fgPercentage>
</BallerStat>
<BallerStat>
<Baller>
<BallerJersey>24</BallerJersey>
<Type>Jersey</Type>
</Baller>
<fgPercentage>
<Type>PERCENT</Type>
<Value>40</Value>
</fgPercentage>
</BallerStat>
</BallerStats>
Underscore-java library can convert json to xml. I am the maintainer of the project. Live example
import com.github.underscore.U;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class MyClass {
#SuppressWarnings("unchecked")
public static void main(String args[]) {
String json = "{\"playerStats\": [\n"
+ "{ \"jerseyNumber\": \"23\", \"fgPercentage\": 60, \"plusMinus\": \"plus\" },"
+ "{ \"jerseyNumber\": \"24\", \"fgPercentage\": 40, \"plusMinus\": \"minus\" }"
+ "] }";
String xml = "<BallerStats>"
+ "<BallerStat>"
+ " <Baller><BallerJersey>23</BallerJersey><Type>Jersey</Type></Baller>"
+ " <fgPercentage><Type>PERCENT</Type><Value>60</Value></fgPercentage>"
+ "</BallerStat>"
+ "</BallerStats>";
List<Map<String, Object>> jsonArray = U.get((Map<String, Object>) U.fromJson( json ), "playerStats");
Map<String, Object> map = new LinkedHashMap<>();
List<Map<String, Object>> ballerStats = new ArrayList<>();
Map<String, Object> ballerStat = new LinkedHashMap<>();
map.put("BallerStats", ballerStat);
ballerStat.put("BallerStat", ballerStats);
for (Map<String, Object> jsonItem : jsonArray) {
Map<String, Object> newBallerStat = (Map<String, Object>) ((Map<String, Object>) ((Map<String, Object>) U.fromXml( xml )).get("BallerStats")).get("BallerStat");
((Map<String, Object>) newBallerStat.get("Baller")).put("BallerJersey", jsonItem.get("jerseyNumber"));
((Map<String, Object>) newBallerStat.get("fgPercentage")).put("Value", jsonItem.get("fgPercentage"));
ballerStats.add(newBallerStat);
}
System.out.println(U.toXml(map));
}
}
I have an xml file like the following:
<?xml version="1.0"?>
<Book>
<Title>Ulysses</Title>
<Author>James <b>Joyce</b></Author>
</Book>
I need to parse this using Java into a pojo like
title="Ulysses"
author="James <b>Joyce</b>"
In other words, I need the html or possible custom xml tags to remain as plain text rather than xml elements, when parsing.
I can't edit the XML at all but it would be ok for me to create a custom xslt file to transform the xml.
I've got the following Java code for using xslt to assist with the reading of the xml,
TransformerFactory factory = TransformerFactory.newInstance();
Source stylesheetSource = new StreamSource(new File(stylesheetPathname).getAbsoluteFile());
Transformer transformer = factory.newTransformer(stylesheetSource);
Source inputSource = new StreamSource(new File(inputPathname).getAbsoluteFile());
Result outputResult = new StreamResult(new File(outputPathname).getAbsoluteFile());
transformer.transform(inputSource, outputResult);
This does apply my xslt to the file which is written out but I can't come up with the correct xslt to do it. I had a look at Add CDATA to an xml file but this does not work for me.
Essentially, I believe I want the file to look like
<?xml version="1.0"?>
<Book>
<Title>Ulysses</Title>
<Author><![CDATA[James <b>Joyce</b>]]></Author>
</Book>
Then I can extract
"James <b>Joyce</b>". I tried the approach suggested here: Add CDATA to an xml file
But it did not work for me.
I used the following xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
<xsl:template match="Author">
<xsl:copy>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="*"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</xsl:template>
and this produced:
<?xml version="1.0" encoding="UTF-8"?>
Ulysses
<Author><![CDATA[
<b>Joyce</b>]]></Author>
Can you please help with this? I want the original document to be written out in it's entirety but with the CDATA surrounding everything within the author element.
Thanks
Isn't using a simple html/xml parser like Jsoup a better way of solving this?
Using Jsoup you can try something like this:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;
public class Example {
public static void main(String[] args) {
String xml = "<?xml version=\"1.0\"?>\n"
+ "<Book>\n"
+ " <Title>Ulysses</Title>\n"
+ " <Author>James <b>Joyce</b></Author>\n"
+ "</Book>";
Document doc = Jsoup.parse(xml, "", Parser.xmlParser());
doc.outputSettings().prettyPrint(false);
Elements books = doc.select("Book");
for(Element e: books){
Book b = new Book(e.select("Title").html(),e.select("Author").html());
System.out.println(b.title);
System.out.println(b.author);
}
}
public static class Book{
String title;
String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
}
}
With XSLT 3.0 as supported by Saxon 9.8 HE (available on Maven and Sourceforge) you can use XSLT as follows:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="xs math"
version="3.0">
<xsl:output cdata-section-elements="Author"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="Author">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:value-of select="serialize(node())"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
As for your attempt, you basically need to "implement" the identity transformation template concisely written in XSLT 3.0 as <xsl:mode on-no-match="shallow-copy"/> as a template
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
in XSLT 1.0 so that those nodes not handled by more specialized template (like the one for Author elements) are recursively copied through.
Then, with the copy-of selecting all child nodes node() and not only the element nodes * you get
<xsl:template match="Author">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="node()"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</xsl:template>
I am able to generate CSV file from XML file using XSLT, but the only header of XML file header is only showing on CSV file. The Values are not showing up.
Here is my java code:-
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
public class xml2csv {
public static void main() throws Exception {
File stylesheet = new File("C:/Users/Admin/Desktop/out.xslt");
File xmlSource = new File("C:/Users/Admin/Desktop/out.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlSource);
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
Source source = new DOMSource(document);
Result outputTarget = new StreamResult(new File("C:/Users/Admin/Desktop/out.csv"));
transformer.transform(source, outputTarget);
}
}
the XML file:-
<root>
<header>Symbol</header>
<row>NIFTY 50</row>
<row>LUPIN</row>
<header>Open</header>
<row>9,670.35</row>
<row>1,082.90</row>
<header>High</header>
<row>9,684.25</row>
<row>1,137.00</row>
</root>
XSLT file:-
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
Symbol,Open,High
<xsl:for-each select="//header">
<xsl:value-of select="concat(Symbol, ',', Open, ',', High)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
So, I am getting only header of XML using this XSLT, where am I going wrong?
If I am guessing correctly at what you're trying to accomplish here, you will need to do something like:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text"/>
<xsl:template match="/root">
<!-- header -->
<xsl:text>Symbol,Open,High
</xsl:text>
<!-- data -->
<xsl:variable name="n" select="count(row) div 3" />
<xsl:for-each select="row[position() <= $n]">
<xsl:variable name="i" select="position()" />
<xsl:text>"</xsl:text>
<xsl:value-of select="."/>
<xsl:text>","</xsl:text>
<xsl:value-of select="../row[$n + $i]"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="../row[2 * $n + $i]"/>
<xsl:text>"
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Applied to your input example, the result will be:
Symbol,Open,High
"NIFTY 50","9,670.35","9,684.25"
"LUPIN","1,082.90","1,137.00"
I have added quotes around the values because some of them contain commas - but I did not handle the possibility of some them containing a quote.
As I mentioned in a comment to your question, this could be a lot easier if your XML were structured in a more friendly way.
========= UPDATE =========
Many thanks to Tomalak for the correct XSL syntax, and to Ian Roberts for pointing out that in order to use namespaces in my XSLT, I need to call "setNamespaceAware(true)" at the very beginning, in my DocumentBuilderFactory.
========= END UPDATE =========
Q: How can I write an XSLT stylesheet that filters out all elements and/or all node trees in the "http://foo.com/abc" namespace?
I have an XML file that looks like this:
SOURCE XML:
<zoo xmlns="http://myurl.com/wsdl/myservice">
<animal>elephant</animal>
<exhibit>
<animal>walrus</animal>
<animal>sea otter</animal>
<trainer xmlns="http://foo.com/abc">Jack</trainer>
</exhibit>
<exhibit xmlns="http://foo.com/abc">
<animal>lion</animal>
<animal>tiger</animal>
</exhibit>
</zoo>
DESIRED RESULT XML:
<zoo xmlns="http://myurl.com/wsdl/myservice">
<animal>elephant</animal>
<exhibit>
<animal>walrus</animal>
<animal>sea otter</animal>
</exhibit>
</zoo>
XSLT (thanks to Tomalak):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://foo.com/abc"
exclude-result-prefixes="a"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="a:* | #a:*" />
</xsl:stylesheet>
Thank you in advance!
JAVA PROGRAM THAT SUCCESSFULLY DOES THE XSLT FILTERING BY NAMESPACE:
import java.io.*;
import org.w3c.dom.*; // XML DOM
import javax.xml.parsers.*; // DocumentBuilder, etc
import javax.xml.transform.*; // Transformer, etc
import javax.xml.transform.stream.*; // StreamResult, StreamSource, etc
import javax.xml.transform.dom.DOMSource;
public class Test {
public static void main(String[] args) {
new Test().testZoo();
}
public void testZoo () {
String zooXml = Test.readXmlFile ("zoo.xml");
if (zooXml == null)
return;
try {
// Create a new document builder factory, and make sure it[s namespace-aware
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder docBuilder = dbf.newDocumentBuilder ();
// Read XFDD input string into DOM
Document xfddDoc =
docBuilder.parse(new StringBufferInputStream (zooXml));
// Filter out all elements in "http://foo.com/abc" namespace
StreamSource styleSource = new StreamSource (new File ("zoo.xsl"));
Transformer transformer =
TransformerFactory.newInstance().newTransformer (styleSource);
// Convert final DOM back to String
StringWriter buffer = new StringWriter ();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); // Remember: we want to insert this XML as a subnode
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(xfddDoc), new StreamResult (buffer));
String translatedXml = buffer.toString();
}
catch (Exception e) {
System.out.println ("convertTransactionData error: " + e.getMessage());
e.printStackTrace ();
}
}
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://foo.com/abc"
exclude-result-prefixes="a"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="a:* | #a:*" />
</xsl:stylesheet>
Empty templates match nodes but do not output anything, effectively removing what they match.