Copy nodes in the same output xml file -java - java

1.This is my example file "example.xml"
<?xml version="1.0" encoding="UTF-8"?>
<VER>7.0</VER>
<NATIONALITY>FIN</NATIONALITY>
<DATA>
<USER>ED</USER>
<PLZ>XXX</PLZ>
<BEGIN>2015-05-16</BEGIN>
<CURRENCY>90</CURRENCY>
<MARKE>KIA</MARKE>
<DATA>
2.This is my java code that parses the file "example.xml" :
public static void main(String argv[]) {
try {
Properties prop = System.getProperties();
File file = new File("E:/workspace/example.xml");
DocumentBuilderFactory dbildfactory =DocumentBuilderFactory.newInstance();
DocumentBuilder dbild = dbildfactory.newDocumentBuilder();
Document doc = dbild.parse(file);
doc.getDocumentElement().normalize();
NodeList nodeL = doc.getElementsByTagName("ALL");
for (int s = 0; s < nodeL.getLength(); s++) {
Node nodde = nodeL.item(s);
if (nodde.getNodeType() == Node.ELEMENT_NODE){
Element fstElmnt = (Element) nodde;
NodeList list = fstElmnt.getElementsByTagName("MARKE");
Element disp = (Element) list.item(0);
NodeList dispmarke = disp.getChildNodes();
System.out.println("<MARKE>" + ((Node)
dispmarke.item(0)).getNodeValue() + "</MARKE>");
String dispbrd = prop.getProperty("prop4");
((Node) dispmarke.item(0)).setNodeValue(dispbrd);
System.out.println("<MARKE>" + ((Node)
dispmarke.item(0)).getNodeValue() + "</MARKE>");
if(dispmarke.item(0).getNodeValue().equals("LEX") ){
NodeList nod = fstElmnt.getElementsByTagName("MARKE");
Element element = (Element) nod.item(0);
NodeList mod = element.getChildNodes();
System.out.println("<MARKE>" + ((Node) mod.item(0)).getNodeValue() + "</MARKE>");
prop.put("norm", "X300");
((Node) mod.item(0)).setNodeValue(prop.getProperty("norm"));
System.out.println("<MARKE>" + ((Node) mod.item(0)).getNodeValue() + "</MARKE>");
}
}
}
TransformerFactory transformerFactory =
TransformerFactory.newInstance();
Transformer transformer =
transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult console = new StreamResult(System.out);
StreamResult fil = new StreamResult(new File("E:/workspace/res/output.xml"));
transformer.transform(source, console);
transformer.transform(source, fil);
}
catch (Exception e) {
e.printStackTrace();
}
}
3.At this time, the nodes are saved to a new file "output.xml":
<?xml version="1.0" encoding="UTF-8"?>
<ALL>
<VER>7.0</VER>
<NATIONALITY>FIN</NATIONALITY>
<DATA>
<USER>ED</USER>
<PLZ>XXX</PLZ>
<BEGIN>2015-05-16</BEGIN>
<CURRENCY>90</CURRENCY>
<MARKE>KIA</MARKE>
<DATA>
</ALL>
4.I would like that, there were several copies of nodes in file output.xml.
Everyone this node started after the last node:
<?xml version="1.0" encoding="UTF-8"?>
<ALL>
<VER>7.0</VER>
<NATIONALITY>FIN</NATIONALITY>
<DATA>
<USER>ED</USER>
<PLZ>XXX</PLZ>
<BEGIN>2015-05-16</BEGIN>
<CURRENCY>90</CURRENCY>
<MARKE>KIA</MARKE>
<DATA>
</ALL>
<ALL>
<VER>7.0</VER>
<NATIONALITY>FIN</NATIONALITY>
<DATA>
<USER>ED</USER>
<PLZ>XXX</PLZ>
<BEGIN>2015-05-16</BEGIN>
<CURRENCY>90</CURRENCY>
<MARKE>KIA</MARKE>
<DATA>
</ALL>
...
5.How can the easiest way to do this in Java? What loops used for this?

I had to fix your input XML to have a root element:
<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
<VER>7.0</VER>
<NATIONALITY>FIN</NATIONALITY>
<DATA>
<USER>ED</USER>
<PLZ>XXX</PLZ>
<BEGIN>2015-05-16</BEGIN>
<CURRENCY>90</CURRENCY>
<MARKE>KIA</MARKE>
</DATA>
</ROOT>
Then I could use XMLBeam (A data projection library, DISCLOSURE: I'm affiliated with this project) to
read the input,
wrap it into an ALL Element
duplicate the input and
print it out
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import org.xmlbeam.XBProjector;
import org.xmlbeam.XBProjector.Flags;
import org.xmlbeam.annotation.XBWrite;
import org.xmlbeam.dom.DOMAccess;
#SuppressWarnings("javadoc")
public class DuplicateNode {
// Projection to embed some nodes into an "ALL" element
public interface AllNodes {
#XBWrite("./*")
AllNodes setNodes(List<DOMAccess> nodes);
};
// Projection for the output document
public interface OutputProjection {
#XBWrite("/ROOT/*")
void setNodes(List<AllNodes> nodes);
};
public static void main(String[] args) throws IOException {
// Create the projector we will use to project the data
XBProjector projector = new XBProjector(Flags.TO_STRING_RENDERS_XML);
//Read all nodes from input document
List<DOMAccess> nodes =projector.io().url("res://example.xml").evalXPath("/ROOT/*").asListOf(DOMAccess.class);
// Create some copies
List<AllNodes> newNodeList = new LinkedList<AllNodes>();
newNodeList.add(projector.projectEmptyElement("ALL",AllNodes.class).setNodes(nodes));
newNodeList.add(projector.projectEmptyElement("ALL",AllNodes.class).setNodes(nodes));
//...
// Create an output projection that will take the copied nodes
OutputProjection outputProjection = projector.projectEmptyDocument(OutputProjection.class);
// set nodes to the output projection
outputProjection.setNodes(newNodeList);
// print it out (or write to file, stream,...)
System.out.println(outputProjection);
}
}
This program prints out:
<ROOT>
<ALL>
<VER>7.0</VER>
<NATIONALITY>FIN</NATIONALITY>
<DATA>
<USER>ED</USER>
<PLZ>XXX</PLZ>
<BEGIN>2015-05-16</BEGIN>
<CURRENCY>90</CURRENCY>
<MARKE>KIA</MARKE>
</DATA>
</ALL>
<ALL>
<VER>7.0</VER>
<NATIONALITY>FIN</NATIONALITY>
<DATA>
<USER>ED</USER>
<PLZ>XXX</PLZ>
<BEGIN>2015-05-16</BEGIN>
<CURRENCY>90</CURRENCY>
<MARKE>KIA</MARKE>
</DATA>
</ALL>
</ROOT>

Related

How to pass a XML document to XSL file using Javax.xml.transformer API?

I am using javax.xml.transform API to do XSL transformation . The API only allows one XML document as an input to apply transformation as below .
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
StringWriter stringWriter = new StringWriter();
File xml = new File("C:\\abc");
File xsl = new File("C:\\def.xsl");
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(xml);
TransformerFactory transformerFactory =
TransformerFactory.newInstance();
StreamSource style = new StreamSource(xsl);
Transformer transformer = transformerFactory.newTransformer(style);
DOMSource source = new DOMSource(document);
Also , can pass simple String params as below , without any issue as below :
transformer.setParameter("mode", "CREATE");
But , i want to pass an XML Document as a parameter to the XSL file . I tried below code as suggested on one of SO pages , as below :
DocumentBuilder builder = factory.newDocumentBuilder();
final Document documentFile = builder.parse(xml2);
Map<String, Document> docs = new HashMap<String, Document>();
docs.put("lookup", documentFile);
transformer.setURIResolver(new DocumentURIResolver(docs));
And i set , the tag in XML to receive value as below :
<xsl:variable name="lookup" select="('documentFile')/> .
But its not working for me . Can anyone help me out with the correct pay to pass multiple XML documents to any XSL file via javax.xml.transform API ?
Update
Still stuck with the issue ,can any one let me how can i pass XML object into a XSLT 2.0 stylesheet as a param . I have tried different approaches but no luck still . I need to know a way out via JAVA xsl transform API .
I think your issue is in the XSLT. Change
<xsl:variable name="lookup" select="('documentFile')/> .
to
<xsl:variable name="lookup" select="document('lookup')/>
this will cause the transformer to make the DOM of your document accessible in the variable lookup. The key lookup comes from docs.put("lookup", documentFile);
Dynamically Pass Multiple XML Sources to XSL Transformation via URIResolver.
Full Working Example:
Be there three XML files: repo.xml, books.xml and articles.xml. The repo.xml contains status information about books and articles. The files articles.xml and books.xml contain title information about each item. The goal is to print status information of all books and articles together with the title information. The entries in all files are connected via id keys.
Find complete example at github or copy/paste the listings below.
repo.xml
<repository>
<book>
<id>1</id>
<status>available</status>
</book>
<book>
<id>2</id>
<status>lost</status>
</book>
<article>
<id>1</id>
<status>in transit</status>
</article>
</repository>
books.xml
<books>
<book id="1">
<title>Book One</title>
</book>
<book id="2">
<title>Book Two</title>
</book>
<book id="3">
<title>Book Three</title>
</book>
</books>
articles.xml
<articles>
<article id="1">
<title>Article One</title>
</article>
<article id="2">
<title>Article Two</title>
</article>
<article id="3">
<title>Article Three</title>
</article>
</articles>
join.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<titleStatusJoin>
<xsl:for-each select="//book">
<xsl:variable name="myId" select="id" />
<book>
<status>
<xsl:value-of select="status" />
</status>
<title>
<xsl:for-each select="document('bookFile')//book">
<xsl:variable name="bookId" select="#id" />
<xsl:choose>
<xsl:when test="$myId = $bookId">
<xsl:value-of select="title" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</title>
</book>
</xsl:for-each>
<xsl:for-each select="//article">
<xsl:variable name="myId" select="id" />
<article>
<status>
<xsl:value-of select="status" />
</status>
<title>
<xsl:for-each select="document('articleFile')//article">
<xsl:variable name="bookId" select="#id" />
<xsl:choose>
<xsl:when test="$myId = $bookId">
<xsl:value-of select="title" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</title>
</article>
</xsl:for-each>
</titleStatusJoin>
</xsl:template>
</xsl:stylesheet>
Use this Java code...
#Test
public void useMultipleXmlSourcesInOneXsl3() {
InputStream xml = Thread.currentThread().getContextClassLoader().getResourceAsStream("stack54335576/repo.xml");
InputStream xsl = Thread.currentThread().getContextClassLoader().getResourceAsStream("stack54335576/join3.xsl");
InputStream booksXml = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("stack54335576/books.xml");
InputStream articlesXml = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("stack54335576/articles.xml");
Document booksDom = readXml(booksXml);
Document articlesDom = readXml(articlesXml);
Map<String, Document> parameters = new HashMap<>();
parameters.put("bookFile", booksDom);
parameters.put("articleFile", articlesDom);
xslt(xml, xsl, parameters);
}
public final void xslt(InputStream xml, InputStream xsl, Map<String, Document> parameters) {
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xsl));
transformer.setURIResolver((href, base) -> new DOMSource(parameters.get(href)));
transformer.transform(new StreamSource(xml), new StreamResult(System.out));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Document readXml(InputStream xmlin) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
return db.parse(xmlin);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
...to produce this output
<?xml version="1.0" encoding="UTF-8"?>
<titleStatusJoin>
<book>
<status>available</status>
<title>Book One</title>
</book>
<book>
<status>lost</status>
<title>Book Two</title>
</book>
<article>
<status>in transit</status>
<title>Article One</title>
</article>
</titleStatusJoin>
Did you already try this ?
org.w3c.dom.Document doc = ... // Your xml document
transformer.setParameter("demo", doc.getDocumentElement());
(Answer expanded to handle passing in a parsed W3C DOM document via a URIResolver)
This can be done in pure XSLT/XPath using the version of the Xalan XSLT processor that is supplied with the JRE.
As an example, say if the name of one of the input documents is passed in as a parameter to the Transformer:
File parentDir = new File("c:\\dir");
StringWriter stringWriter = new StringWriter();
File xml = new File(parentDir, "input.xml");
File xsl = new File(parentDir, "xslt-document-param.xslt");
Source xsltSource = new StreamSource(xsl);
Source xmlSource = new StreamSource(xml);
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer(xsltSource);
transformer.setParameter("doc-name", "basic.xml");
transformer.transform(xmlSource, new StreamResult(stringWriter));
System.out.println(stringWriter);
This parameter can then be passed into the document() function in XPath as follows:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan"
version="1.0"
exclude-result-prefixes="xalan">
<xsl:output
method="xml"
indent="yes"
xalan:indent-amount="2"/>
<xsl:param name="doc-name"/>
<xsl:template match="/">
<xsl:variable name="doc-content" select="document($doc-name)"/>
<parent>
<xsl:for-each select="$doc-content/basic/*">
<child>
<xsl:value-of select="name(.)"/>
</child>
</xsl:for-each>
</parent>
</xsl:template>
</xsl:stylesheet>
This is able to read this basic.xml (from the parameter):
<basic>
<one/>
<two/>
<three/>
</basic>
And transform it to:
<parent>
<child>one</child>
<child>two</child>
<child>three</child>
</parent>
The parameter to the document() function is a URI. A relative path is resolved relative to the XSL file. Equally this could be a full URL, or resolved via a custom transformer.setURIResolver() as in the question.
(edit from here...)
To work with passing in a pre-parsed Document object to the XSLT, the URIResolver approach is able to handle passing this back to the document() function.
For example, with the lookup in the question:
File lookupXml = new File(parentDir, "basic.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(lookupXml);
Map<String, Document> docs = new HashMap<>();
docs.put("lookup", document);
transformer.setURIResolver((href, base) -> new DOMSource(docs.get(href)));
This XSL is able to iterate through the same basic.xml as above...
<xsl:template match="/">
<xsl:variable name="doc-content" select="document('lookup')"/>
<parent>
<xsl:for-each select="$doc-content/basic/*">
<child>
<xsl:value-of select="name(.)"/>
</child>
</xsl:for-each>
</parent>
</xsl:template>
... and output the same result.
Not sure about your issue , if you give usecase and ask how to solve will be more helpful insted of asking how to fix your code as we are not having end to end visiblity of your code and xml.
Following could be possible solution :
1) We can convert xml to string
try {
StringReader _reader = new StringReader("<xml>vkhan</xml>");
StringWriter _writer = new StringWriter();
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(
new javax.xml.transform.stream.StreamSource("styler.xsl"));//ur xsl
transformer.transform(
new javax.xml.transform.stream.StreamSource(_reader),
new javax.xml.transform.stream.StreamResult(_writer));
String result = writer.toString();
} catch (Exception e) {
e.printStackTrace();
}
2) Modify below code as per your requirments pass as List of object of call in for loop.
public class Data {
public static final Document transformXmlDocument(Document sourceDocument, InputStream xsltFile) {
DOMSource xmlSource = new DOMSource(sourceDocument);
StreamSource xsltSource = new StreamSource(xsltFile);
Document transformedData = null;
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xsltSource);
ByteArrayOutputStream output = new ByteArrayOutputStream();
StreamResult result = new StreamResult(output);
transformer.transform(xmlSource, result);
DocumentBuilder resultBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
transformedData = resultBuilder.parse(
new InputSource(
new StringReader(
new String(output.toByteArray())
)
)
);
} catch (Exception e) {
Log.e("XSLT Transformation", e.getMessage());
}
return transformedData;
}
}
https://gist.github.com/dazfuller/1559935/b84ee72db0e1de8ea25c54fbc744defbe4705ad9
Try to replace your <xsl:variable name="lookup" select="('documentFile')"/> instruction with <xsl:variable name="documentFile" select="document($lookup)"/> and pass your XML Document as a parameter with transformer.setParameter("lookup", "myfile.xml"); which means : load the document referenced by the lookup parameter into the documentFile variable.
See also Extract data from External XML file using XSL

XML to CSV conversion using java, tag with colon problem

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");
}

How to read data from xml attributes recurssively and store it in CSV in Java

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 ...

How to delete <?xml version="1.0" encoding="UTF-8" standalone="no"?> from xml document [duplicate]

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

how to get how many node with certain attributes with DOM

I have a task to parse an XML file with JDom in Eclipse. When I started to create the code, my code is only sufficient to get the length(how many) node with Tag name model. The task is more specific, I need to get the length of the node with tag name model which has attribute type. How should I modify my code to get the result?
This is part of my XML file
<container>
<models>
<model id="FM1" type="BoQ">
<meta
<phase phaseDesc="PRCR>SLCT>"/>
<domain domainCode="SPM.BOQ.RFP "/>
<levelOfDetail levelOfDetailCode="[4]"/>
</meta>
</model>
<model id="FM2" type="Object">
<meta>
<phase phaseDesc="PRCR>SLCT> "/>
<domain domainCode="BIM"/>
<levelOfDetail levelOfDetailCode="[4] "/>
</meta>
</model>
<model id="FM3">
<meta>
<phase phaseDesc="PRCR>SLCT>"/>
<domain domainCode="SPM.QTO"/>
<levelOfDetail levelOfDetailCode="[5]"/>
</meta>
</model>
<model id="FM4" type="BoQ">
<meta>
<phase phaseDesc="PRCR>SLCT>"/>
<domain domainCode="TSM.TSC"/>
<levelOfDetail levelOfDetailCode="[3]"/>
</meta>
</model>
</models>
<linkModels>
<linkModel id="LM1" type="QuantitySplit">
<meta>
<info>
<i k="ModelName" v="Linkmodell"/>
</info>
<domain domainCode="LKM.QSP" domainDesc="Link Model"/>
</meta>
<models>
<model id="FM1"/>
<model id="FM2"/>
<model id="FM3"/>
<model id="FM4"/>
</models>
</container>
public class xmldom {
public static void main(String[] args) {
Document xmlDoc = getDocument("./src/MMT_Angebot_Anfrage.xml");
System.out.println("Root: "+
xmlDoc.getDocumentElement().getNodeName());
NodeList model = xmlDoc.getElementsByTagName("model");
System.out.println("Number of Models " +
model.getLength());
String elementPhase = "phase";
String elementDomain = "domain";
String elementLOD = "levelOfDetail";
String attrPhase = "phaseCode";
String attrDomain = "domainCode";
String attrLOD = "levelOfDetailCode";
getElementAndAttrib(model, elementPhase, elementDomain, elementLOD, attrPhase, attrDomain, attrLOD);
}
private static Document getDocument(String docString) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setValidating(true);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new InputSource(docString));
}
catch(Exception ex) {
System.out.println(ex.getMessage());
}
return null;
}
private static void getElementAndAttrib(NodeList model,
String elementPhase, String elementDomain, String elementLOD,
String attrPhase, String attrDomain, String attrLOD) {
try {
for(int i=0; i < model.getLength(); i++){
Node modelNode = model.item(i);
Element modelElement = (Element)modelNode;
NodeList phaseList = modelElement.getElementsByTagName(elementPhase);
NodeList domainList = modelElement.getElementsByTagName(elementDomain);
NodeList lodList = modelElement.getElementsByTagName(elementLOD);
Element phaseElement = (Element)phaseList.item(0);
Element domainElement = (Element)domainList.item(0);
Element lodElement = (Element)lodList.item(0);
NodeList elementList = phaseElement.getChildNodes();
System.out.println("=================================================");
System.out.println(attrPhase + " : "+ phaseElement.getAttribute(attrPhase));
System.out.println(attrDomain + " : "+ domainElement.getAttribute(attrDomain));
System.out.println(attrLOD + " : "+ lodElement.getAttribute(attrLOD));
}
}
catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
You want to count the number of <model> elements that contains the type attribute? If, so XPath is the most suitable tool.
XPath xp = XPathFactory.newInstance().newXPath();
Double num = xp.evaluate("count(//model[#type])", doc, XPathConstants.NUMBER);
Btw, you are using DOM, not JDOM.

Categories