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")
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'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 + "]/#*";
TextView Naziv[];
TextView Id[];
int a = 0;
//ovaj primjer sam nasao na netu, treba parsirat XML
//ali nisam siguran da li treba podatke parsirat u ovoj klasi ili u nekoj drugoj
//probaj to skuzit
try{
String address = "http://www.dajsve.com/rss.ashx?svigradovi=1";
URL gradoviXmlUrl = new URL(address);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(gradoviXmlUrl.openStream());
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("Grad");
Naziv = new TextView[nodeList.getLength()];
List<Grad> gradoviLista = null;
for(int i=0; i<nodeList.getLength(); i++){
Element element = (Element) nodeList.item(i);
NodeList nazivGrada = element.getElementsByTagName("Naziv");
NodeList idGrada = element.getElementsByTagName("Id");
Element nazivGradaElement = (Element) nazivGrada.item(i);
Element idGradaElement = (Element) idGrada.item(i);
String gradNaziv = nazivGradaElement.getAttribute("Naziv");
/*Grad grad = null;
grad.setNaziv(nazivGrada);
grad.setId(idGradaElement);
gradoviLista.add(idGradaElement, nazivGradaElement);*/
}
a = nodeList.getLength();
//ovdje u varijablu zapisujem broj gradova, koje kasnije koristim samo za provjeru u main aktivitiju
The fetch from web service works, in variable a i store the length of elements, but the storing into variables does'nt work.
Element element = (Element) nodeList.item(i);
NodeList nazivGrada = element.getElementsByTagName("Naziv");
NodeList idGrada = element.getElementsByTagName("Id");
Element nazivGradaElement = (Element) nazivGrada.item(i);
Element idGradaElement = (Element) idGrada.item(i);
String gradNaziv = nazivGradaElement.getAttribute("Naziv");
This code does'nt work.
this is the xml: http://www.dajsve.com/rss.ashx?svigradovi=1
Can somebody help me?
nodeList.item(i); returns the node at the indexth position in the NodeList, a Node is not always an element so you will get a ClassCastException on:
Element element = (Element) nodeList.item(i);
Just make sure to check if(FPN.getNodeType() == Node.ELEMENT_NODE) before casting a Node to an Element
Or you can use:
Node node = nodeList.item(i);
String gradNaziv = getNodeValueByTagName(node ,"Naziv");
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'm using DOM to parse xml, but have run into an issue. In my xml i have three tags namely str, int and str. Now while parsing i get the same value for both the str tags whereas they should be different.
My XML
<result name="response" numFound="62996" start="0">
<doc>
<str name="body">
a b c d e f g h i j k l m n o p q r s t u v w x y z
</str>
<int name="content_id">123351</int>
<str name="title">
Alphabets
</str>
</doc>
</result>
Code for xml parsing
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(gXml));
Document doc = db.parse(is);
NodeList infraline1 = doc.getElementsByTagName(node);
sb.append("<results count=");
sb.append("\"10\"");
sb.append(">\r\n");
for (int i = 0; i < infraline1.getLength(); i++) {
Node node1 = infraline1.item(i);
if (node1.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node1;
NodeList nodelist = element.getElementsByTagName("str");
Element element1 = (Element) nodelist.item(0);
NodeList body = element1.getChildNodes();
sb.append("<result>\r\n");
sb.append("<body>");
sb.append((body.item(0)).getNodeValue().trim());
sb.append("</body>\r\n");
if (node1.getNodeType() == Node.ELEMENT_NODE) {
Element element2 = (Element) node1;
NodeList nodelist1 = element2.getElementsByTagName("int");
Element element3 = (Element) nodelist1.item(0);
NodeList id = element3.getChildNodes();
sb.append("<id>");
sb.append(id.item(0).getNodeValue().trim());
sb.append("</id>\r\n");
}
if(node1.getNodeType() == Node.ELEMENT_NODE){
Element element4 = (Element) node1;
NodeList nodelist2 = element4.getElementsByTagName("str");
Element element5 = (Element) nodelist2.item(0);
NodeList title = element5.getChildNodes();
sb.append("<title>");
sb.append(title.item(0)).getNodeValue());
sb.append("</title>\r\n");
}
sb.append("</result>\r\n");
}
}
sb.append("</results>");
}
Please help as i need to get different values for both str node
I only see the statements
Element element1 = (Element) nodelist.item(0);
and
Element element3 = (Element) nodelist.item(0);
Are you sure, you are accesing the right elements.
... and by the way. The code is really confused, because you are parsing and writing data at once. Try to put the parsed XML into an own Object or Map and than write (format) it