I made a minimal example to reproduce the problem. This is the transformation (mini.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="/">
<foo>
<xsl:copy-of select="."/>
</foo>
</xsl:template>
</xsl:stylesheet>
and this is the input (mini.xml):
<?xml version="1.0" encoding="utf-8"?>
<bar xmlns:x="baz">
<x:baz/>
</bar>
When I apply the transformation with
xsltproc mini.xsl mini.xml
the result looks as expected:
<?xml version="1.0"?>
<foo>
<bar xmlns:x="baz">
<x:baz/>
</bar>
</foo>
However, when I run the transformation with the following Java program,
import java.io.FileInputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class Program
{
public static void main(String[] args)
{
try
{
Source transform = new StreamSource(new FileInputStream(args[0]));
Templates templates = TransformerFactory.newInstance().newTemplates(transform);
Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(args[1]));
Result result = new StreamResult(System.out);
templates.newTransformer().transform(new DOMSource(input), result);
}
catch (TransformerFactoryConfigurationError | ParserConfigurationException | SAXException | IOException | TransformerException e)
{
e.printStackTrace();
}
}
}
the result looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar xmlns:x="baz">
<baz/>
</bar>
</foo>
(notice that the x: prefix in front of baz is missing.)
Why is that?
And what can I do about it (to preserve the namespace prefix)?
For what I can only assume are historical reasons, DocumentBuilderFactory is non-namespace-aware by default. You need to explicitly switch on namespaces before you do newDocumentBuilder().
It would also be better to use the parse method that takes a File directly rather than creating your own FileInputStream (which your code is not closing once the parse is finished), and likewise with the StreamSource from which the Transformer is built.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document input = dbf.newDocumentBuilder().parse(new File(args[1]));
Related
My problem is in getting the first child of an XML node using the getFirstChild().
My xml is very basic, as follows :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<network name="beep">
<layers number="3">
<layer index="0" lenght="3">
...
</layer>
<layer index="1" lenght="3">
...
</layer>
....
</layers>
</network>
Java-code
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.StringReader;
import org.xml.sax.InputSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
try {
DocumentBuilderFactory DBF = DocumentBuilderFactory.newInstance();
DocumentBuilder DB = DBF.newDocumentBuilder();
Document doc = DB.parse(new InputSource( new StringReader(Xml)));
doc.getDocumentElement().normalize();
Element root = doc.getDocumentElement();
NodeList Nodes =root.getElementsByTagName("network");
Node Layers = Nodes.item(0).getFirstChild();
}
catch (Exception ex)
{
}
as you can see there is an element which is a child of "network" and it is a "layer".
I can successfully access to the network, getting the list of nodes, which is basically one node, but as soon as I try to get the first child of the first (and only) node with :
Node Layers = Nodes.item(0).getFirstChild();
I get an exception, and, even funnier, the exception is null.
Where's the problem?
Please try below code(both Files):
1) XML File:
_________
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<network name="beep">
<layers number="3">
<layer index="0" lenght="3">Hare</layer>
<layer index="1" lenght="3">Rama</layer>
<layer index="0" lenght="3">Hare</layer>
<layer index="1" lenght="3">Krishna</layer>
</layers>
</network>
**************************************************************
2) Java File:
__________
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class XMLDemo {
public static void main(String...lsdfs) {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
try {
InputStream inputStream = XMLDemo.class.getClassLoader().getResourceAsStream("dataFilePackage/XmlData.xml");
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(inputStream);
NodeList nodeList = document.getElementsByTagName("network");
System.out.println(nodeList.item(0).getTextContent());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
I modified your xml to :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<network name="beep">
<layers number="3">
<layer index="0" lenght="3">Vishwa</layer>
<layer index="1" lenght="3">Ratna</layer>
</layers>
</network>
Java code:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class Main {
public static void main(String[] args) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream inputStream = Main.class
.getClassLoader().getResourceAsStream("resources/nodes.xml");
Document doc = builder.parse(inputStream);
NodeList nodes = doc.getElementsByTagName("network");
System.out.println(nodes.item(0).getTextContent());
} catch (FileNotFoundException | ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
O/P
Vishwa
Ratna
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");
}
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.
I have the xml data as follows below,
<?xml version="1.0" encoding="ISO-8859-1"?>
<FIXML xsi:schemaLocation="http://www.fixprotocol.org/FIXML-5-0-SP2 fixml-main-5-0-SP2_.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" s="2012-04-23" v="FIX.5.0SP2">
<Batch ID="RPTTA111PUBLI20170509">
<MktDef MktID="XEUR" MktSegID="14" EfctvBizDt="2017-05-11" NxtEfctvBizDt="2017-05-15" MktSeg="CONF" MarketSegmentDesc="FUT 8-13 Y. SWISS GOV.BONDS 6%" Sym="CH0002741988" ParentMktSegmID="FBND" Ccy="CHF" MktSegStat="1" USFirmFlag="Y" PartID="2">
<MtchRules MtchRuleProdCmplx="5" MtchAlgo="PT" />
<MtchRules MtchRuleProdCmplx="1" MtchAlgo="PT" />
<FlexProdEligs FlexProdEligCmplx="5" FlexProdElig="Y" />
<BaseTrdgRules QtSideInd="1" FastMktPctg="0">
<TickRules TickRuleProdCmplx="1" StartTickPxRng="0" EndTickPxRng="99999.9999" TickIncr="0.01" />
<TickRules TickRuleProdCmplx="5" StartTickPxRng="0" EndTickPxRng="99999.9999" TickIncr="0.01" />
<QuotSizeRules MinBidSz="1" MinOfrSz="1" FastMktInd="0" />
<QuotSizeRules MinBidSz="1" MinOfrSz="1" FastMktInd="1" />
<PxRngRules PxRngRuleID="75" PxRngProdCmplx="1" StartPxRng="0" EndPxRng="99999.9999" PxRngValu="0.15" />
<PxRngRules PxRngRuleID="347" PxRngProdCmplx="5" StartPxRng="0" EndPxRng="99999.9999" PxRngValu="0.12" />
</BaseTrdgRules>
<MDFeedTyps MDFeedTyp="HS" MDBkTyp="2" MktDepth="10" MDRcvryTmIntvl="120000" SvcLctnID1="224.0.50.102" SvcLctnSubID1="59500" SvcLctnID2="224.0.50.230" SvcLctnSubID2="59500" />
<MDFeedTyps MDFeedTyp="HI" MDBkTyp="2" MktDepth="10" MktDepthTmIntvl="0" SvcLctnID1="224.0.50.103" SvcLctnSubID1="59501" SvcLctnID2="224.0.50.231" SvcLctnSubID2="59501" />
<MDFeedTyps MDFeedTyp="HI" MDBkTyp="3" MktDepthTmIntvl="0" SvcLctnID1="224.0.114.97" SvcLctnSubID1="59501" SvcLctnID2="224.0.114.113" SvcLctnSubID2="59501" />
<MDFeedTyps MDFeedTyp="HS" MDBkTyp="3" SvcLctnID1="224.0.114.96" SvcLctnSubID1="59500" SvcLctnID2="224.0.114.112" SvcLctnSubID2="59500" />
<MDFeedTyps MDFeedTyp="L" MDBkTyp="2" MktDepth="5" MktDepthTmIntvl="3500" MDRcvryTmIntvl="30000" SvcLctnID1="224.0.50.89" SvcLctnSubID1="59500" SvcLctnID2="224.0.50.217" SvcLctnSubID2="59500" />
</MktDef>
<SecDef PriSetPx="158.39">
<Instrmt ID="408805" Src="M" SecTyp="FUT" Status="1" ProdCmplx="1" CFI="FFMPSX" MatDt="2017-06-08" MMY="201706" Mult="1" ValMeth="FUT" SettlMeth="P" SettlSubMeth="4" PxPrcsn="2" MinPxIncr="0.01" MinPxIncrAmt="10">
<AID AltID="1048612" AltIDSrc="M" />
<AID AltID="XF000001RQD8" AltIDSrc="4" />
<Evnt EventTyp="7" Dt="2017-06-08" />
</Instrmt>
<MktSegGrp MktSegID="14">
<SecTrdgRules>
<BaseTrdgRules>
<PxRngRules PxRngRuleID="75" />
</BaseTrdgRules>
</SecTrdgRules>
</MktSegGrp>
</SecDef>
</Batch>
</FIXML>
I want to read the data from this XML and store it in CSV file as below.
Column names should be the RootElementName_ChildElementName(if we have)_AttributeName. This format I should follow,
Suppose RootElement is FIXML and we have attributes "s" and "v" so the column name should be as follows FIXML_s, FIXML_v.
And the Child Elements Batch and MktDef the column names should be
FIXML_Batch_ID and FIXML_Batch_MktDef_MktID like that it follows.
1) FIXML_s FIXML_v FIXML_Batch_ID FIXML_Batch_MktDef_MktID . . . . .
"2012-04-23" "FIX.5.0SP2" RPTTA111PUBLI20170509 XEUR ....
.
.
.
We have data like that for thousands of lines and when it reaches to the "</SecDef>" the data should print in 2nd line and 3rd line like that it continues.
Can someone guide me on this. I am very new to working on XML data.
You can take this is as a sample
where
you have to desgn your own
style.xsl
hear is mine
<?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="/">
topic,title,url
<xsl:for-each select="//topic"><xsl:value-of select="#id" /><xsl:value-of select="concat(',' , title, ',' , url,' ')" /></xsl:for-each></xsl:template>
</xsl:stylesheet>
this is the converter
import org.w3c.dom.Document;
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;
public class XMLToCSV {
public static void main(String args[]) throws Exception {
File stylesheet = new File("/home/1/style.xsl");
File xmlSource = new File("/home/1/xml.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("/home/1/howto.csv"));
transformer.transform(source, outputTarget);
System.out.println("Done.");
}
}
You can formatt the output as you want using this
This is how my xml looks like
<?xml version="1.0"?>
<howto>
<topic id="1">
<title>Java</title>
<url>http://www.google.com</url>
</topic>
<topic id="2">
<title>XML</title>
<url>http://www.ab</url>
</topic>
<topic id="3">
<title>Javascript</title>
<url>http://www.tt</url>
</topic>
<topic id="4">
<title>VBScript</title>
<url>http://www.wewe</url>
</topic>
</howto>
Hope this helped ...
This question already has answers here:
Remove 'standalone="yes"' from generated XML
(13 answers)
Closed 9 years ago.
I wrote code for tests - it creates simple XML document. My problem is that created document contains unneeded data in first node . Is any way to delete or modify this node <?xml version="1.0" encoding="UTF-8" standalone="no"?> ?
import java.io.ByteArrayOutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class MyTestClass {
public static void main(String argv[]) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("company");
doc.appendChild(rootElement);
// staff elements
Element staff = doc.createElement("Staff");
rootElement.appendChild(staff);
// firstname elements
Element firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode("yong"));
staff.appendChild(firstname);
// lastname elements
Element lastname = doc.createElement("lastname");
lastname.appendChild(doc.createTextNode("mook kim"));
staff.appendChild(lastname);
// nickname elements
Element nickname = doc.createElement("nickname");
nickname.appendChild(doc.createTextNode("mkyong"));
staff.appendChild(nickname);
// salary elements
Element salary = doc.createElement("salary");
salary.appendChild(doc.createTextNode("100000"));
staff.appendChild(salary);
Transformer t = TransformerFactory.newInstance().newTransformer();
ByteArrayOutputStream s = new ByteArrayOutputStream();
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
t.transform(new DOMSource(doc),new StreamResult(s));
System.out.println(new String(s.toByteArray()));
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
}
}
}
It returns:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<company>
<Staff>
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</Staff>
</company>
Is any way to delete or modify this node <?xml version="1.0" encoding="UTF-8" standalone="no"?> ?
You can add the following to your Transformer
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
see here for details