Strange XML output from Java - java

Recently I made an app that works without errors. It takes user input from texfields(ID, brand, model, type, price and inStock) and writes it to different datasources. I have an interface with methods that the different datasourceclasses implements. I also use a factory to select the DAO-type. Now for practice purpose I've made another app that has EXACTLY the same code, the only difference is couple of different datatypes, for instance the "price" which is a double. I'm having trouble with XML.
I type in all the textfields and press my "add" button and this is a bit of the errormessage:
Exception in thread "JavaFX Application Thread" java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at javafx.DAOProduktXMLFile.getProducts(DAOProduktXMLFile.java:137)
at javafx.GUI_Pane$Lyssnare.handle(GUI_Pane.java:167)
And my XML turns out like this, ID 1 was there before, it was ID number 2 I was trying to add:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<produkter>
<produkt id="1">
<brand>Toyz</brand>
<model>Firetruck</model>
<type>Vehichle</type>
<price>199.0</price>
<inStock>true</inStock>
</produkt>
<produkt id="2">
<brand>false</brand>
<model/>
<type/>
<price/>
<inStock/>
</produkt>
</produkter>
Here's the add-method:
#Override
public void add(DTOProduct dtoProduct) {
doc = getDOMDocument();
Element root = doc.getDocumentElement();
Element produkt = doc.createElement("produkt");
product.setAttribute("id", String.valueOf(dtoProduct.id));
Element brand = doc.createElement("brand");
brand.setTextContent(dtoProduct.brand);
Element model = doc.createElement("model");
brand.setTextContent(dtoProduct.model);
Element type = doc.createElement("type");
brand.setTextContent(dtoProduct.type);
Element price = doc.createElement("price");
brand.setTextContent(String.valueOf(dtoProduct.price));
Element inStock = doc.createElement("inStock");
brand.setTextContent(String.valueOf(dtoProduct.inStock));
product.appendChild(brand);
product.appendChild(model);
product.appendChild(type);
product.appendChild(price);
product.appendChild(inStock);
root.appendChild(produkt);
writeToXML(doc);
}
Get DOM document method:
private Document getDOMDocument() {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(new File("products.xml"));
} catch (SAXException ex) {
} catch (IOException ex) {
} catch (ParserConfigurationException ex) {
}
return doc;
}
Finally, writeToXML method:
private void writeToXML(Document doc) {
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.com/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("products.xml"));
transformer.transform(source, result);
} catch (TransformerException ex) {
Logger.getLogger(DAOProduktXMLFile.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have no clue what's wrong. Like I said, all this code is basically copy-pasted from my other working app and then modified to fit my new datatypes, and it was no problem with textfile, mysql or excel, but XML just don't work!
Any ideas?

Related

My XML is not exporting elements. Why?

I've been working on a tool to convert data into the Collada .DAE format, which is XML based. Unfortunately, one thing has been stopping me: My exported XML doesn't have any of my elements!
Here's the code. I've made it easy-to-read so that you don't have to go through as much of the trouble of reading it.
public class DAEExport {
private static boolean alreadyConstructed = false;
private static Document doc = null;
private static Element root = null;
private static Element lib_images_base_element = null;
private static Element lib_geometry_base_element = null;
private static Element lib_control_base_element = null;
private static Element lib_visual_scene_base_element = null;
public static void AppendData() {
//Normally this method would have the data to append as its args, but I'm not worried about that right now.
//Furthermore, ASSUME THIS RUNS ONLY ONCE (It runs once in the test code I'm using to run this method)! I know that it won't work if called multiple times, as the below variables for the document builder and such wouldn't exist the second time around
try {
if (!alreadyConstructed) {
alreadyConstructed = true;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document document = docBuilder.newDocument();
Element rootElement = document.createElement("SomeGenericElement");
rootElement.appendChild(document.createTextNode("Generic test contents");
document.appendChild(rootElement);
doc = document;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void Build(File _out) {
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
alreadyConstructed = false;
doc = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
Ok so here's my problem: Despite adding those elements to the document by calling AppendData(), then calling Build() to print the data, I only get the following data:
<?xml version="1.0" encoding="UTF-8"?> - No elements. Just the basic header. This is it.
I don't know if it's because of some silly mistake that I've been oblivious to for the past amount of time, or something else. Any answers as to why my elements disappeared?
Currently, your doc object is not being passed from AppendData() method to Build() method. All Build() uses is an empty doc from declaration: doc = null. Hence, your outcome is empty of nodes (TransformFactory adds the XML header).
Consider returning the doc object from AppendData() to be available at class level for other method (do note you change the void to returned object type). You then redefine doc and pass it into Build():
public static Document AppendData() {
...
doc = document
return(doc)
}
Alternatively, call Build() inside AppendData, passing doc as a parameter:
public static void AppendData() {
...
doc = document
Build(doc, outfile)
}
public static void Build(Document doc, File _out) {
...
}

Marshaller on Windows adds new line at the end of file

I have a project that uses JAXB marshalled XML files in order to compare configuration states of different environments. I noticed that there must be some differences in the implementation of the JAXB marshaller under Windows against the Unix version. When I compare 2 files created on the different platforms, my comparison tool always flags one difference at the end of the file. The file created on Windows has a new line (CR and LF) at the end of the file while the Unix version doesn't have it.
Please note that the issue is not about the difference of the new line characters between both platforms! The Windows marshaller effectively adds a "new line" at the end of the file while the Unix marshaller stops after the closing ">" of the root tag.
Is there any parameter I can pass to the marshaller in order to prevent this additional line or do I have to explicitly remove it after marshalling on Windows, so that my comparison tool doesn't flag the difference?
This is how the marshalling code looks like:
public void marshal(final Object rootObject, final OutputStream outputStream) throws JAXBException, TransformerException {
Preconditions.checkArgument(rootObject != null, "rootObject must not be null");
Preconditions.checkArgument(outputStream != null, "outputStream must not be null");
final JAXBContext ctx = JAXBContext.newInstance(rootObject.getClass());
final Document document = getFactories().newDocument();
document.setXmlStandalone(true);
final Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setSchema(schema);
marshaller.marshal(rootObject, document);
createTransformer().transform(new DOMSource(document), new StreamResult(outputStream));
}
public static Transformer createTransformer() {
final Transformer transformer = getFactories().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, JAXBDefaults.OUTPUT_CHARSET.name());
transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, CDATA_XML_ELEMENTS);
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", IDENT_LENGTH);
return transformer;
}
private static class JAXBFactories {
private DocumentBuilderFactory documentBuilderFactory;
public DocumentBuilderFactory getDocumentBuilderFactory() {
if (documentBuilderFactory == null) {
documentBuilderFactory = DocumentBuilderFactory.newInstance();
}
return documentBuilderFactory;
}
private DocumentBuilder documentBuilder;
public DocumentBuilder getDocumentBuilder() {
if (documentBuilder == null) {
try {
documentBuilder = getDocumentBuilderFactory().newDocumentBuilder();
} catch (final ParserConfigurationException ex) {
throw new RuntimeException("Failed to create DocumentBuilder", ex);
}
}
return documentBuilder;
}
public Document newDocument() {
return getDocumentBuilder().newDocument();
}
private TransformerFactory transformerFactory;
public TransformerFactory getTransformerFactory() {
if (transformerFactory == null) {
transformerFactory = TransformerFactory.newInstance();
}
return transformerFactory;
}
public Transformer newTransformer() {
try {
return getTransformerFactory().newTransformer();
} catch (final TransformerConfigurationException ex) {
throw new RuntimeException("Failed to create Transformer", ex);
}
}
}
private static class FactoriesHolder {
static final JAXBFactories FACTORIES = new JAXBFactories();
}
private static JAXBFactories getFactories() {
return FactoriesHolder.FACTORIES;
}
There is no reason (or expectation) that pretty-printing XML will produce exactly the same results from two different systems. It does, however, seem likely that if you switched off the pretty printing (and let yourt IDE/editor do that) you are likely to discover that the output is the same.
Pretty-printing XML is a transform of the original that adds layout. It is no longer real xml.

Can we create testng.xml file on a fly?

I am trying to create a UI which will show all the methods inside the project having #Test annotation. This will give the user an option to select the method which they want to execute during run time.
My intention is when user selects let say Method1 and Method3 from the UI, code should create a testng.xml file with Method1 and Method3 and pass that xml file for the execution.
Is there any way of doing this ? Any help is much appreciated. Thanks.
Yes, you can create TestNG at run time.
I have written utility to read all the test cases and and value designated by Y and N, depicting that if that test case has to be run or not. And the testng can be created accordingly. You can read values as selected from UI.
Below code can be of help to you:
public static void createTestNg() {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
Document doc = dbBuilder.newDocument();
Element rootElement = doc.createElement("suite");
doc.appendChild(rootElement);
Attr rootNameAttribute = doc.createAttribute("name");
rootNameAttribute.setValue("Suite");
Attr rootParallelAttribute = doc.createAttribute("parallel");
rootParallelAttribute.setValue("none");
rootElement.setAttributeNode(rootNameAttribute);
rootElement.setAttributeNode(rootParallelAttribute);
Element testElement = doc.createElement("test");
rootElement.appendChild(testElement);
Attr testNameAttribute = doc.createAttribute("name");
testNameAttribute.setValue("Test1");
testElement.setAttributeNode(testNameAttribute);
Element classesElement = doc.createElement("classes");
testElement.appendChild(classesElement);
Fillo fillo = new Fillo();
Connection con = fillo.getConnection("./testCaseStatus.xls");
String query = "Select * from Sheet1";
Recordset recordSet = con.executeQuery(query);
while (recordSet.next()) {
if (recordSet.getField("Execute").equals("Y")) {
Element classElement = doc.createElement("class");
Attr classNameAttribute = doc.createAttribute("name");
classNameAttribute.setValue(recordSet.getField("TestCase"));
classElement.setAttributeNode(classNameAttribute);
classesElement.appendChild(classElement);
}
}
recordSet.close();
con.close();
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("./testNg.xml"));
transformer.transform(source, result);
// Output to console for testing
StreamResult consoleResult = new StreamResult(System.out);
transformer.transform(source, consoleResult);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FilloException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I have used fillo.jar to read from excel. You can use any other utility as required.
testng.xml is not mandatory.
You can have your own implementation of IMethodInterceptor where you will launch the GUI and then filter the methods you want.

After making changes in XML file, old data is loading in Java application

I am making some changes to an embedded XML file in my Java application. I have some fields, a LOAD button and a SAVE button. After clicking the save button I can see the XML file updating, but after clicking the load button the old values are being loaded to the fields.
Here is my code:
public class MyLoad_SaveSampleProject {
public String field1 = "";
public String field2 = "";
public void loadSampleProject() {
InputStream file = MyLoad_SaveSampleProject.class.getResourceAsStream("/main/resources/otherClasses/projects/SampleProject.xml");
try {
DocumentBuilderFactory DocBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder DocBuilder = DocBuilderFactory.newDocumentBuilder();
Document Doc = DocBuilder.parse(file);
NodeList list = Doc.getElementsByTagName("*"); //create a list with the elements of the xml file
for (int i=0; i<list.getLength(); i++) {
Element element = (Element)list.item(i);
if (element.getNodeName().equals("field1")) {
field1 = element.getChildNodes().item(0).getNodeValue().toString();
} else if (element.getNodeName().equals("field2")) {
field2 = element.getChildNodes().item(0).getNodeValue().toString();
}
}
} catch (Exception e) {
System.out.println(e);
}
}
public void saveSampleProject(String field1Str, String field2Str) {
InputStream file = MyLoad_SaveSampleProject.class.getResourceAsStream("/main/resources/otherClasses/projects/SampleProject.xml");
try {
DocumentBuilderFactory DocBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder DocBuilder = DocBuilderFactory.newDocumentBuilder();
Document Doc = DocBuilder.parse(file);
NodeList list = Doc.getElementsByTagName("*"); //create a list with the elements of the xml file
for (int i=0; i<list.getLength(); i++) {
Node thisAttribute = list.item(i);
if (thisAttribute.getNodeName().equals("field1")) {
thisAttribute.setTextContent(field1Str);
} else if (thisAttribute.getNodeName().equals("field2")) {
thisAttribute.setTextContent(field2Str);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(Doc);
StreamResult result = new StreamResult(new File("src/main/resources/otherClasses/projects/SampleProject.xml"));
transformer.transform(source, result);
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SAXException sae) {
sae.printStackTrace();
}
}
public String returnField1() {
return field1;
}
public String returnField2() {
return field2;
}
}
And this is my default XML file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Strings>
<field1>string1</field1>
<field2>string2</field2>
</Strings>
When the save button is pressed I am using the saveSampleProject method. When the load button is pressed I am using the loadSampleProject method and then I am getting the field values with the returnField1 and returnField2 methods.
I have no idea of what could be wrong with what I'm doing. I would appreciate any suggestions.
Most probably that calling method getResourceAsStream() leads to resource caching. Since you are using File() in save method try to get InputStream on data load using File object, and not as resource.

Java XML Transformer Only Outputs XML Header

I'm working on a bit of a project for my own amusement that involves outputting the contents of several variables to an XML file. However, when I put the program, the transformer only outputs the first line (the XML header) and nothing else. The saveData() method is called before writeFile(), and I've outputted the value of the variables to the console before calling writeFile() so I know they have a value.
Code below:
public class Output {
private static double citySizeMiles;
private static double citySizeAcres;
private CityType type;
private static int gpLimit;
private static long totalWealth;
private static long cityPopulation;
public static void saveData() {
cityPopulation = CityGenerator.cityPop;
citySizeMiles = City.getCitySizeMiles(cityPopulation);
citySizeAcres = City.getCitySizeAcres(cityPopulation);
gpLimit = City.getGoldLimit();
totalWealth = CityGenerator.cityWealth;
}
public static void writefile() {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = docFactory.newDocumentBuilder();
// Root Elements
Document doc = builder.newDocument();
Element root = doc.createElement("data");
// Data Element
Element data = doc.createElement("City");
root.appendChild(data);
Attr attr = doc.createAttribute("name");
attr.setValue("Test");
data.setAttributeNode(attr);
// City size (sq miles)
Element sizeMi = doc.createElement("sizeMiles");
sizeMi.appendChild(doc.createTextNode(String.valueOf(citySizeMiles)));
data.appendChild(sizeMi);
// City size (acres)
Element sizeAc = doc.createElement("sizeAcres");
sizeAc.appendChild(doc.createTextNode(String.valueOf(citySizeAcres)));
data.appendChild(sizeAc);
// Population
Element pop = doc.createElement("population");
pop.appendChild(doc.createTextNode(String.valueOf(cityPopulation)));
data.appendChild(pop);
// GP limit
Element gpLim = doc.createElement("gpLimit");
gpLim.appendChild(doc.createTextNode(String.valueOf(gpLimit)));
data.appendChild(gpLim);
// Total fluid wealth
Element wealth = doc.createElement("totalWealth");
wealth.appendChild(doc.createTextNode(String.valueOf(totalWealth)));
data.appendChild(wealth);
// Write to XML file
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", 4);
Transformer trans = tf.newTransformer();
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.METHOD, "xml");
DOMSource source = new DOMSource(doc);
//StreamResult result = new StreamResult(new File("D:\\test.xml"));
StreamResult result = new StreamResult(System.out);
trans.transform(source, result);
} catch(ParserConfigurationException pce) {
pce.printStackTrace();
} catch(TransformerException tfe) {
tfe.printStackTrace();
}
}
}
I'm no expert on DOM (I avoid it like the plague, and encourage everyone else to do likewise) but I think you have failed to connect the root element to the document node.

Categories

Resources