I have a program that creates an xml doc.
the filename is unimportant here because the file does get created successfully
the arraylist of entries contains a Unique identifier and a hashmap of
elements + values. the elements are as follows: world, name, location, type and data
all these values are strings and the only one that would ever be blank/null is data
my problem is that the xml file adds all the fields as required with the exception
of the data field. it leaves me with an unopened node . actual result:
<NPC>
<NPC:0>
<name>
the_name
</name>
<data/> <---- this line should have the string "null"
<loc>
2529.1294962948955:
69.0:
951.2612160649056
</loc>
<type>
Quest
</type>
<world>
world
</world>
</NPC:0>
</NPC>
My method for creating the xml file.
public void updateXML(String fileName, ArrayList<XMLEntry> entries)
{
File file = getFileByName(fileName);
try {
DocumentBuilderFactory bFac = DocumentBuilderFactory.newInstance();
DocumentBuilder b = bFac.newDocumentBuilder();
Document doc = b.parse(file);
for(int i = 0; i < entries.size(); i++)
{
XMLEntry entry = entries.get(i);
Node entry_node = doc.getElementsByTagName(entry.getName()).item(0);
if(entry_node == null)
{
Element node = doc.createElement(entry.getName());
doc.getFirstChild().appendChild(node);
entry_node = doc.getElementsByTagName(entry.getName()).item(0);
}
for (Map.Entry<String, String> attributes : entry.getAttributes().entrySet())
{
NamedNodeMap xml_attributes = entry_node.getAttributes();
Node attribute = xml_attributes.getNamedItem(attributes.getKey());
if(attribute == null)
{
if(attributes.getValue() != "" || attributes.getValue() != null)
{
Element new_xml_attribute = doc.createElement(attributes.getKey());
new_xml_attribute.appendChild(doc.createTextNode(attributes.getValue()));
entry_node.appendChild(new_xml_attribute);
} else {
Element new_xml_attribute = doc.createElement(attributes.getKey());
new_xml_attribute.appendChild(doc.createTextNode("null"));
entry_node.appendChild(new_xml_attribute);
}
} else {
attribute.setTextContent(attributes.getValue());
}
TransformerFactory tFac = TransformerFactory.newInstance();
Transformer ts = tFac.newTransformer();
DOMSource src = new DOMSource(doc);
StreamResult result = new StreamResult(file);
ts.transform(src, result);
}
}
} catch (ParserConfigurationException e) {
} catch (TransformerException e1) {
} catch (IOException e2) {
} catch (SAXException e3) {
}
}
<data/> <---- this line should have the string "null"
That isn't an XML close-element tag (which would be </data>). It's an XML empty-element tag, which combines open and close into a single piece of markup. It is semantically identical to <data></data>.
Despite your expectations, it would appear that the empty <data/> element is not being created by the path with the literal "null". Drop a printout into that code, or run it in the debugger, to confirm this. Then use the debugger, or drop in additional printouts as necessary, to figure out why.
Related
im new here , just wanted to try if i can get some help here.
I would like to ask for some help for my problem.
I got an XML-File, and i would like to compare those Strings there with File extension for exmaple. Example.txt -> compare all Strings in XML with my File-Extension.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href"tx ?>
<zip>
<exclusions>
<switch> .bak </switch>
<switch> .tmp </switch>
<switch> .frm </switch>
<switch> .opt </switch>
<switch> .met </switch>
<switch> .i </switch>
</exclusions>
</zip>
This is my XML Code to print it , my idea was to store all the Strings into arrays and compare them with my extension .. but i dont know how.
Hope you have some ideas for me.
Thanks
public class xmlFileExten {
public static void main(String[] args) {
try {
File file = new File(xmlFile);
DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = dBuilder.parse(file);
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
if (doc.hasChildNodes()) {
printNote(doc.getChildNodes());
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private static void printNote(NodeList nodeList) {
for (int count = 0; count < nodeList.getLength(); count++) {
Node tempNode = nodeList.item(count);
if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
System.out.println("Node Value =" + tempNode.getTextContent());
You can use following code. Main changes:
1) Using List as result instead of Array,
2) Using textNode AND getNodeValue() instead of getTextContent (getNodeValue returns text only this node),
3) Using recursive function,
public class xmlFileExten
{
public static void main(final String[] args)
{
final List<String> extensionList = getExtensionList("1.xml");
System.out.print(extensionList); // return [.bak, .tmp, .frm, .opt, .met, .i]
}
private static List<String> getExtensionList(final String fileName)
{
final List<String> results = new ArrayList<>();
try
{
final File file = new File(fileName);
final DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
final Document doc = dBuilder.parse(file);
if (doc.hasChildNodes())
{
results.addAll(getExtensionList(doc.getChildNodes()));
}
}
catch (final Exception e)
{
System.out.println(e.getMessage());
}
return results;
}
private static List<String> getExtensionList(final NodeList nodeList)
{
final List<String> results = new ArrayList<>();
for (int count = 0; count < nodeList.getLength(); count++)
{
final Node tempNode = nodeList.item(count);
final String value = tempNode.getNodeValue();
if (tempNode.getNodeType() == Node.TEXT_NODE && value != null && !value.trim().isEmpty())
{
results.add(value.trim());
}
results.addAll(getExtensionList(tempNode.getChildNodes()));
}
return results;
}
}
I think the main problem here is that you are not able to parse it properly . Refer this Parse XML TO JAVA POJO in efficient way
and you can use http://pojo.sodhanalibrary.com/ to get the correct POJO classes required for your task.
After you get the POJO you can compare the extensions
I have the following xml
<Company>
<Company1>
<Dept>
<Name>M1</Name>
<Employers>10</Employers>
<Product>soap</Product>
<Building>001</Building>
<Compulsory>Yes</Compulsory>
</Dept>
<Dept>
<Name>M2</Name>
<Sub-Name>M2-01</Sub-Name>
<Id>m1001</Id>
<Employers>12</Employers>
<Product>soap-cover</Product>
</Dept>
</Company1>
<OtherDetails>
<DeptOther>
<Name>M3</Name>
<Employers>10</Employers>
<Product>soap-colour</Product>
<Building>001</Building>
<Sub>001-01</Sub>
<Compulsory>Yes</Compulsory>
</DeptOther>
</OtherDetails>
</Company>
I need to read this xml and map each of these element to following POJOs.
Object1 - 'Company' which has attributes 'Company1' and 'OtherDetails'
Object2 - 'Company1' which has attributes 'Dept'
Object3 - 'Dept' which has attributes 'Name', 'Employers' etc.
I'm using org.apache.axiom.om.impl.builder.StAXOMBuilder in order to build the DocumentElement.
I'm using following code,
public static void main(String[] args) throws IOException {
mapXMLtoPOJO(FILE_LOCATION);
}
private static boolean mapXMLtoPOJO(String fileLocation) {
File file = new File(fileLocation);
if (file.exists()) {
OMElement fileElement;
try {
InputStream xmlInputStream = new FileInputStream(file);
fileElement = new StAXOMBuilder(xmlInputStream).getDocumentElement();
} catch (Exception e) {
log.error("Error while parsing XML file : " + file.getAbsolutePath());
return false;
}
elementWriter(fileElement);
} else {
return false;
}
return true;
}
public static void elementWriter(OMElement fileElement){
if(fileElement != null){
Iterator iterator1 = fileElement.getChildElements();
int i = 0;
while (iterator1.hasNext()){
OMElement pp = (OMElement) iterator1.next();
log.info(" -------------- " + i);
log.info(" -0-0-0-0-0-0- " + pp.getLocalName() + " ----- " + pp.getText());
i++;
elementWriter(pp);
}
}
}
which print each of the above elements with their values.
But I couldn't find a way to map each of these elements correctly into the java objects created for each major tag as mentioned above.
Should I be store these values in a hash map and then later put them into the created objects? Or what is the most optimum algorithm to do this?
Any idea on how I could do this would be appreciated.
Am trying to read the below xml content using SAXReader
I have to read the child elements of node name "SelogerListController".
The node name "SelogerListController" contains 3 child nodes .
My main aim is to get the 3rd node's child elemnts of node name "SelogerListControllerlike"
src="http://res/Favorite_Badge.png" ,src="http://res/sm_aries.png"
and
src="http://res/sm_cancer.png" and http://res/Favorite_Badge.png
...............
and the remining details also..
Code using
SAXReader reader = new SAXReader();
Document document;
String xPath = "//XREClientView/XREClientView[5]";
String nodeName = null;
List<Element> childViews;
try {
document = reader.read("F://TestNewXMLAfter.xml");
List<Node> nodes = document.selectNodes(xPath);
for (Node node : nodes) {
System.out.println("name :: " + node.valueOf("#name"));
System.out.println(node.getPath());
nodeName = node.valueOf("#name");
if (nodeName.equals("SelogerListController")) {
childViews = ((Element) node).elements();
for (Element element : childViews) {
Element ele = element.element("XREClientImage");
}
break;
}
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The XPath you show in your post is:
//XREClientView/XREClientView[5]
This says find an XREClientView which contains at least five child nodes named XREClientView and return the fifth one. The XPath should start
//XREClientView[#name='SelogerListController']/...
where you can work out what to substitute for .... It's not entirely clear what unique attribute values you can use to find the nodes you're interested in.
This question already has answers here:
Order of XML attributes after DOM processing
(12 answers)
Closed 8 years ago.
I am trying to convert a XML Node to String using the following code :
private String nodeToString(final Node node) {
final StringWriter stringWriter = new StringWriter();
try {
final Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.transform(new DOMSource(node), new StreamResult(stringWriter));
} catch (final TransformerException e) {
JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
return stringWriter.toString();
}
My problem is that it formats attributes of XML node in alphabetical orders. Is there any property I could apply to ignore formatting of Node attributes ?
The DOM API does not preserve attribute order:
NamedNodeMaps are not maintained in any particular order
If you have a Node then you have already lost any attribute ordering. Consider this XML:
<?xml version="1.0" encoding="UTF-8"?>
<!-- attrs.xml -->
<attrs
a="a"
z="z"
b="b"
m="m" />
There are no guarantees about the ordering of the output of this application:
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
public class Attrs {
public static void main(String[] args) throws Exception {
NamedNodeMap attrs = DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.parse("attrs.xml")
.getElementsByTagName("attrs")
.item(0)
.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Attr attribute = (Attr) attrs.item(i);
System.out.println(attribute.getName() + "=" + attribute.getValue());
}
}
}
If they are alphabetical then that is only an implementation side-effect, not a requirement. If attribute order is significant to you then you are using the wrong tools.
I figure it out how to do this, I have read xml file, and read only specific node from that xml file as a string. And applied operations on string to match my conditions. By doing this obviously I cannot leverage the Parser API, but that fulfilled my requirements. Following is my code snippet:
/**
* #param in InputStream of xml file
*/
private String getNodeString(InputStream in) throws IOException {
String nodeString = "";
InputStreamReader is = new InputStreamReader(in);
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(is);
String read = br.readLine();
String fileData;
while (read != null) {
//System.out.println(read);
sb.append(read);
read = br.readLine();
}
fileData = sb.toString().trim();
// Start index of node
int start = fileData.indexOf("<" + mSignedNode);
// End index of node, next node name
int end = fileData.indexOf("</Configuration>");
nodeString = fileData.substring(start, end);
return nodeString.trim();
}
The method is quite dirty, but you can pass parameters to find start index and end index.
Hope this would help someone, rather just closing their question ;)
i want to know if is possible to me to parse some atributes from a xml file, to be a object in java
I donĀ“t wanna to create all fields that are in xml.
So, how can i do this?
For exemple below there is a xml file, and i want only the data inside the tag .
<emit>
<CNPJ>1109</CNPJ>
<xNome>OESTE</xNome>
<xFant>ABATEDOURO</xFant>
<enderEmit>
<xLgr>RODOVIA</xLgr>
<nro>S/N</nro>
<xCpl>402</xCpl>
<xBairro>GOMES</xBairro>
<cMun>314</cMun>
<xMun>MINAS</xMun>
<UF>MG</UF>
<CEP>35661470</CEP>
<cPais>58</cPais>
<xPais>Brasil</xPais>
<fone>03</fone>
</enderEmit>
<IE>20659</IE>
<CRT>3</CRT>
For Java XML parsing where you don't have the XSD and don't want to create a complete object graph to represent the XML, JDOM is a great tool. It allows you to easily walk the XML tree and pick the elements you are interested in.
Here's some sample code that uses JDOM to pick arbitrary values from the XML doc:
// reading can be done using any of the two 'DOM' or 'SAX' parser
// we have used saxBuilder object here
// please note that this saxBuilder is not internal sax from jdk
SAXBuilder saxBuilder = new SAXBuilder();
// obtain file object
File file = new File("/tmp/emit.xml");
try {
// converted file to document object
Document document = saxBuilder.build(file);
//You don't need this or the ns parameters in getChild()
//if your XML document has no namespace
Namespace ns = Namespace.getNamespace("http://www.example.com/namespace");
// get root node from xml. emit in your sample doc?
Element rootNode = document.getRootElement();
//getChild() assumes one and only one, enderEmit element. Use a lib and error
//checking as needed for your document
Element enderEmitElement = rootNode.getChild("enderEmit", ns);
//now we get two of the child from
Element xCplElement = enderEmitElement.getChild("xCpl", ns);
//should be 402 in your example
String xCplValue = xCplElement.getText();
System.out.println("xCpl: " + xCplValue);
Element cMunElement = enderEmitElement.getChild("cMun", ns);
//should be 314 in your example
String cMunValue = cMunElement.getText();
System.out.println("cMun: " + cMunValue);
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You can use JAXB to unmarshal the xml into Java object, with which you can read selective elements easily. With JAXB, the given XML can be represented in Java as follows :
enderEmit element :
#XmlRootElement
public class EnderEmit{
private String xLgr;
//Other elements.Here you can define properties for only those elements that you want to load
}
emit element (This represents your XML file):
#XmlRootElement
public class Emit{
private String cnpj;
private String xnom;
private EnderEmit enderEmit;
..
//Add elements that you want to load
}
Now by using the below lines of code, you can read your xml to an object :
String filePath="filePath";
File file = new File(filePath);
JAXBContext jaxbContext = JAXBContext.newInstance(Emit.class);
jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Emit emit = (Emit) jaxbUnmarshaller.unmarshal(file);
The line will give you an emit object for the given xml.
Try to use StringUtils.subStringBetween
try
{
String input = "";
br = new BufferedReader(new FileReader(FILEPATH));
String result = null;
while ((input = br.readLine()) != null) // here we read the file line by line
{
result = StringUtils.substringBetween(input, ">", "<"); // using StringUtils.subStringBetween to get the data what you want
if(result != null) // if the result should not be null because some of the line not having the tags
{
System.out.println(""+result);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (br != null)
{
br.close();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}