As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have a XML file that I am trying to read and transform into objects. I want to transform and put all the locations in a array filled with Location objects wich are defined by a film id, a date and a amount.
Here is my XML file :
Here is my code to scan the location XML section :
public void findLocations() throws ParseException {
NodeList nList = document.getElementsByTagName("location");
Location[] locations = new Location[nList.getLength()];
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
locations[temp] = new Location(getTagValue("filmid", eElement), dateChanger(getTagValue("date", eElement)), getTagValue("amount", eElement));
System.out.println(locations[temp].getAmount()); //Outputs the good values.
}
}
System.out.println(locations[0].getAmount()); //Output : 5$
System.out.println(locations[1].getAmount()); //Output : 5$
System.out.println(locations[2].getAmount()); //Output : 5$
}
private static String getTagValue(String sTag, Element eElement) {
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
The problem seems that my array is getting filled 3 times with the same location and ends up filled 3 time with the last location. The objects otherwise are well formed, so I imagine I got that part right.
You could use XPath instead...
public class TestXML03 {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
Document xmlDoc = builder.parse(new File("Test.xml"));
Node root = xmlDoc.getDocumentElement();
XPathFactory xFactory = XPathFactory.newInstance();
XPath xPath = xFactory.newXPath();
XPathExpression xExpress = xPath.compile("/file/location");
NodeList nodes = (NodeList) xExpress.evaluate(root, XPathConstants.NODESET);
System.out.println("Found " + nodes.getLength() + " location nodes");
System.out.println("");
for (int index = 0; index < nodes.getLength(); index++) {
Node node = nodes.item(index);
xExpress = xPath.compile("filmid");
Node filmIDNode = (Node) xExpress.evaluate(node, XPathConstants.NODE);
System.out.println(filmIDNode.getNodeName() + " = " + filmIDNode.getTextContent());
xExpress = xPath.compile("date");
Node dateNode = (Node) xExpress.evaluate(node, XPathConstants.NODE);
System.out.println(dateNode.getNodeName() + " = " + dateNode.getTextContent());
xExpress = xPath.compile("amount");
Node amountNode = (Node) xExpress.evaluate(node, XPathConstants.NODE);
System.out.println(amountNode.getNodeName() + " = " + amountNode.getTextContent());
System.out.println("");
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
Which outputs...
Found 3 location nodes
filmid = 100
date = 2013-01-11
amount = 4.00$
filmid = 200
date = 2013-01-13
amount = 9.00$
filmid = 334
date = 2013-01-23
amount = 5.00$
Updated After Feed-back
The Location class is maintaining a static reference to it's class fields, this means that changing the value for the field will change it for all instances of that class.
Remove the static references and it should solve the problem.
Your source is working perfectly. Simply modifying your source to output tags as below.
public static void findLocations(Document document) throws ParseException {
NodeList nList = document.getElementsByTagName("location");
Location[] locations = new Location[nList.getLength()];
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println(getTagValue("filmid", eElement));
System.out.println(getTagValue("date", eElement));
System.out.println(getTagValue("amount", eElement));
System.out.println();
}
}
}
I got the proper output
100
2013-01-11
4.00$
200
2013-01-13
9.00$
334
2013-01-23
5.00$
Check if your XML input is proper.
Related
I am a beginner in using Java programming particularly using Xpath to parse an XML file.
I am trying to develop a system that routes flights according to their weightings. I want to:
Maintain a count of flights for each location;
The system should accept a location and return the number and country to route a flight to. For every 4 flights to Japan, route the next 2 flights to China then route the next 2 flights to India and loop and to return count, continent, location name, country and weight.
I would appreciate any assistance please.
I can pass the XML data of and retrieve the different element nodes using Xpath. I attempted using SAX and STAX but prefered this method as it was clear and concise when constructing the expressions.
XML File Example:
<continent>
<location name = "asia">
<country>Japan</country>
<code>0000011111</code>
<weight>10</weight>
</location>
<location name = "asia">
<country>China</country>
<code>0000022222</code>
<weight>1</weight>
</location>
</continent>
Java Sample Code:
public static void main(String[] args) {
try {
FileInputStream file = new FileInputStream(new File("c:/continents.xml"));
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
System.out.println("*************************");
String expression = "/continent/location";
System.out.println(expression);
String name = xPath.compile(expression).evaluate(xmlDocument);
System.out.println(name);
System.out.println("**********Parse XML File***************");
expression = "/continent/location/country|//number|//weight";
System.out.println(expression);
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
}
System.out.println("*************************");
expression = "/continent/location[#name='asia']/number";
System.out.println(expression);
nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
}
System.out.println("*************************");
expression = "//location[country='China']";
System.out.println(expression);
Node node = (Node) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODE);
if(null != node) {
nodeList = node.getChildNodes();
for (int i = 0;null!=nodeList && i < nodeList.getLength(); i++) {
Node nod = nodeList.item(i);
if(nod.getNodeType() == Node.ELEMENT_NODE)
System.out.println(nodeList.item(i).getNodeName() + " : " + nod.getFirstChild().getNodeValue());
}
}
}
I’m not sure I understand your goal, but if you just want to count how many flights are to a particular country, you can count the matching elements:
NodeList matches = (NodeList) xPath.evaluate(
"//country[text()='" + country + "']",
xmlDocument,
XPathConstants.NODESET);
int matchCount = matches.getLength();
I am receiving a xml payload from a web service call and it is assigned in a String. This xml has 10 elements and I need to change the value of logtime to whatever I want. Since this is a String, is there a way to change any of the element's value.
This is my first java code please let me know if you need more explanation.
code
String xml = dto.getAuditTrail();
Xml
I want to know how can I suppose change the time value of logtime to another format, since this entire xml is a String?
Please help because I am new to it.
Thanks
You need to parse your String in order to obtain a Document object which you can read by tag.
Here you can find how to parse your string, then with Document object you're able to read specific tag:
public void readDocument(Document doc) {
try{
NodeList nList = doc.getElementsByTagName("Event");
System.out.println("----------------------------");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println("LogTime : " + eElement.getElementsByTagName("logTime").item(0).getTextContent());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Source here
This is basic way for xml reading, but you can directly edit the xml too:
public void editDocument() {
try{
NodeList nList = doc.getElementsByTagName("Event");
System.out.println("----------------------------");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
Node logTimeNode = eElement.getElementsByTagName("logTime").item(0);
String logTimeString = logTimeNode.getTextContent();
// Do some stuff with logTimeString
logTimeNode.setTextContent(logTimeString);
}
}
// write the content into xml file
String filepath = "/path/to/file.xml";
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(filepath));
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
I'm having a slight problem with XML parsing.
I'm creating a function where the parameter is a certain "element" from the XML file.
When found, I want to return the value of the root attribute.
Here's my code:
FileInputStream file = new FileInputStream(new File("C:\\Users\\Grizzly\\Java\\Projet_16_17-20161214\\bdd.xml"));
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(file);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("type");
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node nNode = nList.item(temp);
if(nNode.toString().equalsIgnoreCase(element))
{
Element eElement = (Element) nNode;
System.out.println("Taxe= "+ eElement.getAttribute("taxe"));
}
}
}
Any idea on how to do this?
Here's my XML file:
<?xml version="1.0"?>
-<types>
-<type id="Nourriture" taxe="0.1">
<element>pomme</element>
<element>fraise</element>
<element>fromage</element>
<element>viande rouge </element>
</type>
-<type id="Matiere Premiere" taxe="0.2">
<element>fer</element>
<element>polypropylene</element>
</type>
-<type id="Element Solide" taxe="0.3">
<element>voiture</element>
<element>planche surf</element>
<element>pistolet</element>
</type>
</types>
In my code, I tried to get the elements of a certain node from the nodelist and then compare it to the the string "element" which is the input of the user, and if they match it will check the attribute value of taxe linked to it.
Thanks in advance.
EDIT: I'm getting closer to what I need:
NodeList nList = doc.getElementsByTagName("type");
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node nNode = nList.item(temp);
NodeList nChildren = nNode.getChildNodes();
Element eElement = (Element) nNode;
for(int i = 0; i < nChildren.getLength(); i++)
{
String onElement = eElement.getElementsByTagName("element").item(i).getTextContent();
if(onElement.equalsIgnoreCase(element))
{
System.out.println("id : " + eElement.getAttribute("id"));
System.out.println("taxe : " + eElement.getAttribute("taxe"));
break;
}
}
}
But it's only reading the first element... and item(i) isn't working.
Any idea?
If I understand you correctly, you are trying to fetch specific attributes (id and taxe) of all the document nodes having at least one child element with specific name (element).
Although the problem can be solved by iterating the DOM and keeping the states, I would rather delegate this task to XPath. A code with XPath will look cleaner and be more maintainable. For example, in order to fetch all elements having attributes id and taxe and a child element element you can use an XPath expression like //*[#id and #taxe element]. The matching nodes are fetched in a single line. You can simply iterate the nodes and collect the attributes as shown in the following example.
Example
public static void main(String args[]) {
String element = args.length > 0 ? args[0] : "element";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
FileInputStream file = new FileInputStream(new File("/some/file.xml"));
Document doc = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "//*[#id and #taxe and " + element + "]";
NodeList nodeList = (NodeList) xPath.compile(expression)
.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
NamedNodeMap attributes = node.getAttributes();
for (int j = 0; j < attributes.getLength(); j++) {
Node aNode = attributes.item(j);
System.out.printf(
"%s: %s\n",
aNode.getNodeName(),
aNode.getNodeValue()
);
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
Sample Output
id: Nourriture
taxe: 0.1
id: Matiere Premiere
taxe: 0.2
id: Element Solide
taxe: 0.3
Note, the sample above prints all attributes of the parent element. If you want to print only specific ones, you can, obviously, add a trivial check like this:
String aName = aNode.getNodeName();
if (aName.equals("taxe")) { // ...
But you can actually filter out the attributes with XPath:
String expression = "//*[ " + element + "]/#*[name() = 'id' or name() = 'taxe']";
NodeList nodeList = (NodeList) xPath.compile(expression)
.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
System.out.printf("%s: %s\n", node.getNodeName(), node.getNodeValue());
}
The XPath expression above fetches all attribute nodes having names equal to whether id, or taxe. If you want all attributes, simply remove the last condition:
String expression = "//*[ " + element + "]/#*";
I'm trying to parse this XML in Java:
<entities>
<entity name="product_section" id="1">
<product_type>3</product_type>
<section_type>1</section_type>
<name>Empresa</name>
<description>d</description>
<position>1</position>
<align>left</align>
<files section_id="1">
<ico id="ico_1" type="normal" src="sections/1/icons/ico.png"></ico>
<ico id="ico_2" type="hover" src="sections/1/icons/ico.png"></ico>
<ico id="ico_3" type="active" src="sections/1/icons/ico.png"></ico>
<img id="img_1" type="normal" src="sections/1/img/pestanya.png"></img>
<img id="img_2" type="hover" src="sections/1/img/pestanya-hover.png"></img>
<img id="img_3" type="active" src="sections/1/img/pestanya-active.png"></img>
<background id="background_1" type="background" position="1" src="sections/1/background/bg1.png"></background>
<background id="background_2" type="background" position="2" src="sections/1/background/bg2.png"></background>
<background id="background_3" type="background" position="3" src="sections/1/background/bg3.png"></background>
</files>
</entity>
But I just achieved to loop through Entities, getting all Entity and each <product_type>, <section_type>, etc.
But I want to loop through files too.
This is my implementation so far:
try {
File contingut = new File("xmlfile.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(contingut);
doc.getDocumentElement().normalize();
System.out.println("root of xml file " + doc.getDocumentElement().getNodeName());
//loop a cada entity
NodeList nodes = doc.getElementsByTagName("entity");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Element element = (Element) node;
System.out.println("product_type: " + getValue("product_type", element));
System.out.println("section_type: " + getValue("section_type", element));
System.out.println("name: " + getValue("name", element));
System.out.println("description: " + getValue("description", element));
System.out.println("position: " + getValue("position", element));
System.out.println("align: " + getValue("align", element));
}
} catch (Exception e){
e.printStackTrace();
}
getValue function is:
private static String getValue(String tag, Element element) {
NodeList nodes = element.getElementsByTagName(tag).item(0).getChildNodes();
Node node = (Node) nodes.item(0);
return node.getNodeValue();
}
I've done lot of google search, and all I find are "simple" examples, with a parent, and a child, but not child's child.
Any help would be appreciated.
At first one suggestion:
check element type after this Element element = (Element) node;
use this code or something like this :
if (element.getNodeType() == Element.ELEMENT_NODE) { // do smth}
and answer to your question:
You can simply rewrite you code. after you create element you can get all it's child elements by using element.getChildNodes();
it gives you all child tags. After that you write simple for loop where you get each node element from node list like this :
NodeList nodes = element.getChildNodes();
for(int i =0; i < nodes.getLength(); i++){
Element child = (Element) nodes.item(i);
if(child.getNodeType() == Element.ELEMENT_NODE){
String tagName = child.getTagName();
if(!tagName.equals("files")){
System.out.println(tagName + " : " + child.getTextContent());
}else{
NodeList filesChilds = child.getChildNodes();
for(int j = 0; j < filesChilds.getLength(); j++){
//and like above
}
}
}
}
I am currently parsing XML, but im not quite sure how to parse the "status" attribute of "message":
<message status="test"> <text>sometext</text> <msisdn>stuff</msisdn> </message>
Here is the code, i have cut off everything unnecessary:
NodeList nodeLst = doc.getElementsByTagName("message");
for (int s = 0; s < nodeLst.getLength(); s++) {
Node fstNode = nodeLst.item(s);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElmnt = (Element) fstNode;
NodeList numberNmElmntLst = fstElmnt
.getElementsByTagName("msisdn");
Element numberNmElmnt = (Element) numberNmElmntLst.item(0);
NodeList numberNm = numberNmElmnt.getChildNodes();
String phoneNumber = ((Node) numberNm.item(0))
.getNodeValue().substring(2);
NodeList txtNmElmntLst = fstElmnt
.getElementsByTagName("text");
Element txtNmElmnt = (Element) txtNmElmntLst.item(0);
NodeList txtNm = txtNmElmnt.getChildNodes();
String text = ((Node) txtNm.item(0)).getNodeValue();
NodeList rcvNmElmntLst = fstElmnt
.getElementsByTagName("received");
Element rcvNmElmnt = (Element) rcvNmElmntLst.item(0);
NodeList rcvNm = rcvNmElmnt.getChildNodes();
String recievedDate = ((Node) rcvNm.item(0)).getNodeValue();
}
}
Can anyone guide me how this is done?
Thanks in advance.
Node.getAttributes()
NamedNodeMap attributes = fstElmnt.getAttributes();
for (int a = 0; a < attributes.getLength(); a++)
{
Node theAttribute = attributes.item(a);
System.out.println(theAttribute.getNodeName() + "=" + theAttribute.getNodeValue());
}
You could avoid traversing if you use XPATH to retrieve the data. Read this tutorial.
I have been playing with Apache Xerces for parsing DOM. But it was horrible tasks. If you could, take a look at jsoup.
So, if your question has an answer in Jsoup, it would be:
node.attr("status")