I have an xml document to parse which have nested nodes I have tried in my way but unable to get job done as desired.
XML doc is
<Items>
<Item>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51l7DDD1qNL._SL160_.jpg</URL>
<Height Units="pixels">160</Height>
<Width Units="pixels">160</Width>
</MediumImage>
<Title>Fallout 4 Vault Dweller's Survival Guide Collector's Edition: Prima Official Game Guide</Title>
<OfferSummary>
<LowestNewPrice>
<Amount>1952</Amount>
</OfferSummary>
</Item>
.
.
.
</Items>
I have done to fetch Title node values as
private static NodeList fetchTitle(String requestUrl) {
NodeList nodeList = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(requestUrl);
nodeList = doc.getElementsByTagName("Title");
} catch (Exception e) {
System.out.println("Message is " + e.getCause() + "...." + e.getMessage());
throw new RuntimeException(e);
}
return nodeList;
}
and I print as in main() as
titleList = fetchTitle(requestUrl);
for (int i = 0; i < titleList.getLength(); i++) {
Node node = titleList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// do something with the current element
System.out.println(node.getNodeName());
System.out.println("Signed Title is \"" + node.getTextContent() + "\"");
System.out.println();
}
}
and Amount value from LowestNewPrice Node as
private static NodeList fetchPrice(String requestUrl) {
NodeList nodeList = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(requestUrl);
nodeList = doc.getElementsByTagName("LowestNewPrice");
} catch (Exception e) {
System.out.println("Message is " + e.getCause() + "...." + e.getMessage());
throw new RuntimeException(e);
}
return nodeList;
}
and I print as in main() as
priceList = fetchPrice(requestUrl);
for (int i = 0; i < priceList.getLength(); i++) {
Node node = priceList.item(i).getFirstChild();
if (node.getNodeType() == Node.ELEMENT_NODE) {
// do something with the current element
System.out.println(node.getNodeName());
System.out.println("Signed Price is \"" + node.getTextContent() + "\"");
System.out.println();
}
}
through above code I get all Title values first and then I get Amount values separately, but what I really want is to have a POJO class as
public class Item {
String title;
String price;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
and add values to Item object using setTitle(), setPrice(), and return a List<Item>
any help please.
You might try this solution please.
Parse your data and add to List<Item> as :
public static Document fetchRequiredData(String src) {
Document doc = null;
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser;
try {
parser = dbFactory.newDocumentBuilder();
doc= parser.parse(src);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return doc;
}
public static List<Item> parseItemInfo(Document doc){
List<Item> items = new ArrayList<Item>();
NodeList itemNodeList = doc.getElementsByTagName("Item");
for (int i = 0; i < itemNodeList.getLength(); i++) {
Node titleNode = doc.getElementsByTagName("Title").item(i);
Node priceNode = doc.getElementsByTagName("LowestNewPrice").item(i).getFirstChild();
if (titleNode.getNodeType() == Node.ELEMENT_NODE || priceNode.getNodeType() == Node.ELEMENT_NODE ) {
Item item = new Item();
item.setDesc(titleNode.getTextContent());
item.setPrice(priceNode.getTextContent());
items.add(item);
}
}
return items;
}
now your List is ready to test in main() method as
public static void main(String[] args) {
List<Item> items = parseItemInfo(fetchRequiredData(requestUrl));
System.out.println("Printing List<Item> contents ...");
for (Item item : items) {
System.out.println("Title is " + item.getTitle());
System.out.println("Price is " + item.getPrice());
System.out.println();
}
}
Hope this one helps.
You can achieve that by using JAXBContext. First create Item class.
#XmlRootElement(name = "Items")
#XmlAccessorType(value = XmlAccessType.FIELD)
public class Items
{
#XmlElement(name = "Item")
private List<Item> item;
public void setItem(List<Item> itemList)
{
this.item = itemList;
}
public List<Item> getItem()
{
return this.item;
}
}
#XmlRootElement(name = "Item")
#XmlAccessorType(vallue = XmlAccessType.FIELD)
public class Item
{
#XmlElement(name = "MediumImage")
private MediumImage image;
#XmlElement(name = "Title")
private String title;
#XmlElement(name = "OfferSummary")
private OfferSummary summary;
getters();
setters();
}
#XmlRootElement(name = "MediumImage")
#XmlAccessorType(value = XmlAccessType.FIELD)
public class MediumImage
{
#XmlElement(name = "URL")
private String url;
....
}
#XmlRootElement(name = "OfferSummary")
#XmlAccessorType(value = XmlAccessType.FIELD)
public class OfferSummary
{
#XmlElement(name = "LowestNewPrice")
private LowestNewPrice lowestPrice;
....
}
Then from the main method use marshaller and unmarshaller method.
public static void main(String[] args)
{
File xmlFile = new File("file path");
JAXBContext context = JAXBContext.newInstance(Items.class);
//To get POJO from xml
Unmarshaller unmarshaller = context.createUnmarshaller();
Items items = (Items) unmarshaller.unmarshal(xmlFile);
}
Currently it seems that you're separating the prices and titles into 2 lists, if you want to store an item's price and title into a single Item object, you can do something like this:
public class Item {
public static void main(String[] args) {
ArrayList<Item> items = new ArrayList<Item>();
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File("items.xml"));
NodeList itemElements = doc.getElementsByTagName("Item");
for (int i = 0; i < itemElements.getLength(); i++) {
Node itemElement = itemElements.item(i);
NodeList itemChildren = itemElement.getChildNodes();
Item item = new Item();
for (int j = 0; j < itemChildren.getLength(); j++) {
Node n = itemChildren.item(j);
if (n.getNodeName().equalsIgnoreCase("title")) {
item.setTitle(n.getTextContent());
} else if (n.getNodeName().equalsIgnoreCase("OfferSummary")) {
NodeList offerChildren = n.getChildNodes();
for (int k = 0; k < offerChildren.getLength(); k++) {
Node offerChild = offerChildren.item(k);
if (offerChild.getNodeName().equalsIgnoreCase("LowestNewPrice")) {
item.setPrice(offerChild.getTextContent());
}
}
}
}
items.add(item);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("items: " + items);
}
String title;
String price;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
#Override
public String toString() {
return "Title: " + title + " Price: " + price;
}
}
What this does is to get all the <Item> elements from the XML and loop through them to get the item's title and price.
Related
I'm getting hard time in figuring how to write a loop to retrieve values from a given XML document for simplicity I'll give you a sample of the xml file
</solution>
<solution>
<cost>505.9208295302417</cost>
<routes>
<route>
<driverId>noDriver</driverId>
<vehicleId>1_1</vehicleId>
<start>0.0</start>
<act type="service">
<serviceId>5 </serviceId>
<arrTime>109.9819741964403</arrTime>
<endTime>119.9819741964403</endTime>
</act>
<end>229.9639483928806</end>
</route>
<route>
<driverId>noDriver</driverId>
<vehicleId>3_1</vehicleId>
<start>0.0</start>
<act type="service">
<serviceId>4 </serviceId>
<arrTime>109.98190391287031</arrTime>
<endTime>119.98190391287031</endTime>
</act>
<act type="service">
<serviceId>2 </serviceId>
<arrTime>119.98282618841856</arrTime>
<endTime>129.98282618841856</endTime>
</act>
<act type="service">
<serviceId>1 </serviceId>
<arrTime>129.98372097890456</arrTime>
<endTime>139.98372097890456</endTime>
</act>
<act type="service">
<serviceId>3 </serviceId>
<arrTime>139.9846432544528</arrTime>
<endTime>149.9846432544528</endTime>
</act>
<end>259.9668316441239</end>
</route>
</routes>
</solution>
</solutions>
so basically what I've in the code that I'll be showing you is to obtain value from only the node where there is cost = 505.9208295302417, please don't take into account this part of the code, so the next step was to retrieve driverid``, vehicleid and act , I know that there is a missing for loop but I don't know where to put it!! please can someone help. The desired output that i need to have is like for every vehicleid obtain list act values associated with it
java code
public static void main(String[] args) {
try {
int totalVehicle;
totalVehicle = 2;
File fXmlFile = new File("C:/Users/HP/Desktop/solution.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
Double requiredCost = 505.9208295302417;
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
// NodeList nList = doc.getElementsByTagName("route");
System.out.println("----------------------------");
NodeList nodeList = doc.getElementsByTagName("solution");
for (int i = 0; i < nodeList.getLength(); i++) {
Node solutionNode = nodeList.item(i);
if (solutionNode.getNodeType() == Node.ELEMENT_NODE) {
Element solutionElement = (Element) solutionNode;
Node costNode = solutionElement.getElementsByTagName("cost").item(0);
Node route = solutionElement.getElementsByTagName("routes").item(0);
// if correct cost, proceed to parse further
Double costValue = Double.valueOf(costNode.getTextContent());
if (Double.compare(requiredCost, costValue) == 0) {
System.out.println("working");
// there you go, found the node with the cost 505.9208295302417
// now just parse all the node elements you need here
System.out.println("cost : "
+ solutionElement.getElementsByTagName("cost")
.item(0).getTextContent());
for (int h = 0; h < totalVehicle; h++) {
System.out.println("DriverId : "
+ solutionElement.getElementsByTagName("driverId")
.item(h).getTextContent().toString());
System.out.println("vehicleId : "
+ solutionElement.getElementsByTagName("vehicleId")
.item(h).getTextContent());
NodeList optionList = solutionElement.getElementsByTagName("act");
System.out.println(optionList.getLength());
for (int j = 0; j < optionList.getLength(); ++j)
{
for(int k =0;k<1;++k){
Element option = (Element) optionList.item(j);
String optionText = option.getTextContent();
//address.add(optionText.replaceAll("[^A-Za-z]"," "));
System.out.println("Citizen :"+optionText.replaceAll("[^A-Za-z]"," "));}
;
}
As others have suggested, using xpath would be much easier but if it's an absolute requirement that you loop over all this stuff, break the problem into smaller, more manageable pieces. I thought I'd give it a try and I have a complete, working solution to your problem.
The idea is to break xml up into Java objects and use those objects to do the work you need.
public static void main(String... args) throws SAXException, IOException, ParserConfigurationException {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new File("/home/william/Documents/test.xml"));
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("solution");
for (int i = 0; i < nodeList.getLength(); i++) {
Node solutionNode = nodeList.item(i);
try {
System.out.println(Solution.newInstance(solutionNode).toString());
} catch (Exception e) {
// do something
e.printStackTrace();
}
}
}
Here, your original document parsed the same way you did it but Solution is its own class you can put the logic in:
public class Solution {
private final double cost;
private final Collection<Route> routes;
public static final Solution newInstance(Node solution) throws Exception {
return new Solution(solution);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("solution:");
sb.append(System.lineSeparator());
sb.append("--------");
sb.append(System.lineSeparator());
sb.append("cost:");
sb.append(this.cost);
for (Route route : this.routes) {
sb.append(route.toString());
}
return sb.toString();
}
private Solution(Node solution) throws Exception {
if (solution.getNodeType() == Node.ELEMENT_NODE) {
Element solutionElement = (Element) solution;
this.cost = Double.valueOf(solutionElement.getElementsByTagName("cost").item(0).getTextContent());
this.routes = Routes.get(solutionElement.getElementsByTagName("routes").item(0));
} else {
// TODO something?
this.cost = 0D;
this.routes = Collections.emptyList();
}
}
}
Note that in your main method you have a check on the cost. I've left all class variable getter methods out, add the ones you need if you need to read them from outside the object. So for example in your Solution class add a getCost() method and then in the main method you can check as appropriate: if (solution.getCost() == requiredCost) { ...
Here, based on your requirements, you could add getters to the class members if needed. I've just overridden the toString() method in order to print something you can read.
Routes is a util class to create a collection of Route objects out of the child nodes of the <routes> node.
public class Routes {
private final Collection<Route> items;
public static Collection<Route> get(Node routes) throws Exception {
return new Routes(routes).items;
}
private Routes() {
this.items = new ArrayList<>();
}
private Routes(Node routes) throws Exception {
this.items = new ArrayList<>();
NodeList routesList = routes.getChildNodes();
for (int i = 0; i < routesList.getLength(); i++) {
Node route = routesList.item(i);
if (Node.ELEMENT_NODE == route.getNodeType()) {
items.add(Route.newInstance(route));
} else {
// TODO something?
}
}
}
}
The Acts class has similar logic to the Routes class (same thing but for acts):
public class Acts {
private Collection<Act> items;
public static Collection<Act> get(NodeList acts) throws Exception {
return new Acts(acts).items;
}
private Acts() {
this.items = new ArrayList<>();
}
private Acts(NodeList acts) throws Exception {
this.items = new ArrayList<>();
for (int i = 0; i < acts.getLength(); i++) {
Node act = acts.item(i);
if (Node.ELEMENT_NODE == act.getNodeType()) {
this.items.add(Act.newInstance(act));
} else {
// TODO something?
}
}
}
}
and finally, each individual Act:
public class Act {
private final String service;
private final double arrTime;
private final double endTime;
public static Act newInstance(Node act) throws Exception {
return new Act(act);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Act");
sb.append(System.lineSeparator());
sb.append("arr time");
sb.append(System.lineSeparator());
sb.append(this.arrTime);
sb.append(System.lineSeparator());
sb.append("end time:");
sb.append(System.lineSeparator());
sb.append(this.endTime);
sb.append(System.lineSeparator());
sb.append("service:");
sb.append(System.lineSeparator());
sb.append(this.service);
return sb.toString();
}
private Act(Node act) throws Exception {
Element actElement = (Element) act;
this.service = actElement.getAttribute("service");
this.arrTime = Double.valueOf(actElement.getElementsByTagName("arrTime").item(0).getTextContent());
this.endTime = Double.valueOf(actElement.getElementsByTagName("endTime").item(0).getTextContent());
}
}
Good day ppl.
I have class:
public class XmlModifier {
private DocumentBuilderFactory docFactory = null;
private DocumentBuilder docBuilder = null;
private Document document = null;
private TransformerFactory transformFactory = null;
private Transformer transform = null;
private DOMSource source = null;
private StreamResult streamRes = null;
private boolean exepDocBuilderAlarm = true;
public XmlModifier() {
this.docFactory = DocumentBuilderFactory.newInstance();
try {
this.docBuilder = docFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
this.exepDocBuilderAlarm = false;
e.printStackTrace();
}
}
public void prepareXMLMessage(File file, String userName, String userPassword, String reqId, Integer NUMBER_OF_MSG_SENDS) {
if (exepDocBuilderAlarm != false) {
try {
document = docBuilder.parse(file);
setElementValues("si:sourceInfo", addElementsToArray("si:reqId,si:reqTag"), addElementsToArray(reqId + "," + reqId), NUMBER_OF_MSG_SENDS);
setElementValues("usr:user", addElementsToArray("usr:id,usr:password"), addElementsToArray(userName + "," + userPassword), NUMBER_OF_MSG_SENDS);
setElementValues("meth:method", addElementsToArray("meth:id,meth:tag"), addElementsToArray(reqId + "," + reqId), NUMBER_OF_MSG_SENDS);
setElementValues("tb:tradeField", addElementsToArray("tb:value"), addElementsToArray(reqId), NUMBER_OF_MSG_SENDS);
this.transformFactory = TransformerFactory.newInstance();
this.transform = transformFactory.newTransformer();
this.source = new DOMSource(document);
this.streamRes = new StreamResult(file);
this.transform.transform(source, streamRes);
System.out.println("Done to execute XmlModifier");
} catch (Exception e) {
e.printStackTrace();
} finally {
this.docFactory = null;
this.docBuilder = null;
this.transformFactory = null;
this.transform = null;
this.source = null;
this.streamRes = null;
}
}
}
private void setElementValues(String rootElement, String[] childElements, String[] childElementsValues, Integer msgIDIncrement) {
Node nodeRootElement = document.getElementsByTagName(rootElement).item(0);
NodeList childElementlist = nodeRootElement.getChildNodes();
for (int i = 0; i < childElements.length; i++) {
for (int z = 0; z < childElementlist.getLength(); z++) {
Node node = childElementlist.item(z);
if (childElements[i].equals(node.getNodeName())) {
node.setTextContent(childElementsValues[i]);
}
}
}
}
private String[] addElementsToArray(String elements) {
String[] theArray = null;
theArray = elements.split(",");
return theArray;
}
}
On input I have xml which is not well formed sometimes. The problem of DOM parser is that in my point of view DOM parser parsing whole xml from the beggining which my have special symbols like < > & " ' is not good for me.
How can I on input to prepareXMLMessage(..) provide xml with < > & " ', then in prepareXMLMessage(..) parse it with no problems(change some values inside elements) and than as output provide xml with < > & " ' back???
Thank you for help.
I am trying to Parse the below XML file and create an JTree based on it.
<OBJECTS>
<WINDOW NAME = "WINDOW 01" URL = "URL 01">
<PAGE NAME = "PAGE 01" URL = "PAGE URL 01">
</PAGE>
</WINDOW>
</OBJECTS>
The "WINDOW 01" is getting added to the root node "Object List", but the "PAGE 01" node is not getting displayed under the "WINDOW 01" node. The source code used is given below. Please Help!!!
public class DataNode extends DefaultMutableTreeNode {
private static final long serialVersionUID = 1L;
public String ObjectType, ObjectName, URL, ElementType;
public DefaultMutableTreeNode node;
public DataNode(DefaultMutableTreeNode node, Element element) {
this.node = node;
this.ObjectType = element.getTagName();
this.ObjectName = element.getAttribute("NAME");
this.URL = element.getAttribute("URL");
this.ElementType = element.getAttribute("TYPE");
}
public DataNode(Element element) {
this.node = new DefaultMutableTreeNode("OBJECT");
this.ObjectType = element.getTagName();
this.ObjectName = "Object List";
this.URL = "";
this.ElementType = "";
}
#Override
public String toString() {
return this.ObjectName;
}
}
This is the main class. No errors or warnings are displayed on compiling.
public class MyOwn {
private JFrame contentsFrame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MyOwn window = new MyOwn();
window.contentsFrame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MyOwn() {
contentsFrame = new JFrame();
contentsFrame.setTitle("My JTree");
contentsFrame.setBounds(100, 100, 549, 738);
contentsFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTree objectListTree = new JTree(convertXMLtoTree("G:/Collection.xml"));
objectListTree.setAlignmentY(Component.TOP_ALIGNMENT);
objectListTree.setAlignmentX(Component.LEFT_ALIGNMENT);
contentsFrame.getContentPane().add(new JScrollPane(objectListTree));
}
private DefaultMutableTreeNode convertXMLtoTree(String Path) {
NodeList nWindow, nPage;
DefaultMutableTreeNode dRoot, dWindow, dPage;
DataNode xRoot, xWindow, xPage;
try {
File fXmlFile = new File(Path);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
xRoot = new DataNode(doc.getDocumentElement());
dRoot = new DefaultMutableTreeNode(xRoot);
nWindow = doc.getDocumentElement().getElementsByTagName("WINDOW");
for (int i = 0; i < nWindow.getLength(); i++) {
dWindow = new DefaultMutableTreeNode(((Element)(nWindow.item(i))).getAttribute("NAME"));
xWindow = new DataNode(dWindow, (Element)(nWindow.item(i)));
dRoot.add(xWindow);
nPage = ((Element)(nWindow.item(i))).getElementsByTagName("PAGE");
for (int j = 0; j < nPage.getLength(); j++) {
dPage = new DefaultMutableTreeNode(((Element)(nPage.item(j))).getAttribute("NAME"));
xPage = new DataNode(dPage, (Element)(nPage.item(j)));
dWindow.add(xPage);
}
}
return dRoot;
} catch (Exception e) {
return null;
}
}
}
Add your custom DefaultMutableTreeNode DataNode to child node for WINDOW 01 rather than the dWindow which never gets added to the JTree. Replace
dWindow.add(xPage);
with
xWindow.add(xPage);
I use Simple XML (simple-xml-2.6.2.jar) to parse xml file like:
<?xml version="1.0" encoding="UTF-8" ?>
<orderList>
<order id="1">
<name>NAME1</name>
</order>
<order id="2">
<name>NAME2</name>
</order>
</orderList>
The root Element contains subElements.
I wanna it be ArrayList, How to do it?
Here's a possible solution, hope it helps you:
Annotations of Order class:
#Root(name="order")
public class Order
{
#Attribute(name="id", required=true)
private int id;
#Element(name="name", required=true)
private String name;
public Order(int id, String name)
{
this.id = id;
this.name = name;
}
public Order() { }
// Getter / Setter
}
Example class, containing the list:
#Root(name="elementList")
public class Example
{
#ElementList(required=true, inline=true)
private List<Order> list = new ArrayList<>();
// ...
}
And here's some code for reading your code:
Serializer ser = new Persister();
Example example = ser.read(Example.class, file); // file = your xml file
// 'list' now contains all your Orders
List is an interface, ArrayList is one of its implementation, like:
List<Order> l = new ArrayList<Order>()
So if you have a List , you basically have what you want.
If I've interpreted your question correctly, you want a list of orders. I've not tested this for your setup but this works for me for a similar xml structure (assumes you have a custom class called Order):
List<Order> orders = new ArrayList<Order>();
XMLDOMParser parser = new XMLDOMParser();
AssetManager manager = context.getAssets();
InputStream stream;
try {
stream = manager.open("test.xml"); //need full path to your file here - mine is stored in assets folder
Document doc = parser.getDocument(stream);
}catch(IOException ex){
System.out.printf("Error reading xml file %s\n", ex.getMessage());
}
NodeList nodeList = doc.getElementsByTagName("order");
for (int i = 0; i < nodeList.getLength(); i++) {
Element e = (Element) nodeList.item(i); //each order item
Node order=nodeList.item(i);
subList = order.getFirstChild(); //get the name child node
orders.add(order);
}
//XMLDOMParser Class
public class XMLDOMParser {
//Returns the entire XML document
public Document getDocument(InputStream inputStream) {
Document document = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(inputStream);
document = db.parse(inputSource);
} catch (ParserConfigurationException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (SAXException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (IOException e) {
Log.e("Error: ", e.getMessage());
return null;
}
return document;
}
/*
* I take a XML element and the tag name, look for the tag and get
* the text content i.e for <employee><name>Kumar</name></employee>
* XML snippet if the Element points to employee node and tagName
* is name I will return Kumar. Calls the private method
* getTextNodeValue(node) which returns the text value, say in our
* example Kumar. */
public String getValue(Element item, String name) {
NodeList nodes = item.getElementsByTagName(name);
return this.getTextNodeValue(nodes.item(0));
}
private final String getTextNodeValue(Node node) {
Node child;
if (node != null) {
if (node.hasChildNodes()) {
child = node.getFirstChild();
while(child != null) {
if (child.getNodeType() == Node.TEXT_NODE) {
return child.getNodeValue();
}
child = child.getNextSibling();
}
}
}
return "";
}
}
So I have an XML file in the format:
<projectlist>
<project>
<name>test</name>
<type>deploy</type>
<environment>dev</environment>
<server>test01</server>
<server>test02</server>
<server>test03</server>
</project>
</projectlist>
I'm trying to parse this file and build an object that I can populate a JListBox with the names and a radiobutton group with the different servers, however each project consists of a different amount of servers. How do I iterate the nodes/childnodes to build the object with multiple servers. Here is snippets of the code I'm using borrowed from a website and some from me and I'm not very good at coding yet so bear with me please. When I debug it starts to parse & build the object but once it gets to the server names it prints a null pointer exception so I'm doing something totally wrong.
public class XMLParser {
public Project currentProject = new Project();
public void parseXML() throws Exception {
try {
File file = new File("c:\\projectlist.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("project");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
currentProject.SetAppName(getTagValue("name", eElement));
currentProject.SetType(getTagValue("type", eElement));
currentProject.SetEnvironment(getTagValue("environment", eElement));
currentProject.SetServerName(getTagValue("server", eElement));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
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();
}
public final class Project {
protected String AppName = null;
protected String Type = null;
protected List<String> ServerNames = null;
protected String Environment = null;
public void SetAppName(String AppName) {
this.AppName = AppName;
}
public void SetType(String DeployType) {
this.Type = DeployType;
}
public void SetServerName(String ServerName) {
this.ServerNames.add(ServerName);
}
public void SetEnvironment(String Environment) {
this.Environment = Environment;
}
public String getAppName() {
return AppName;
}
public String getType() {
return Type;
}
public List<String> getServerName() {
return ServerNames;
}
public String getEnvironment() {
return Environment;
}
}
Your exception is being caused because you didn't initialize ServerNames in your Project class. Try to initialize it as follows and rerun:
final protected List<String> ServerNames = new ArrayList<String>();
If your xml was created using an xsd schema, you could instead use JAXB to create classes for it, using the xjc tool. That should make your life a bit easier.