getNodeValue() returns some random string - java

I have an android project with file res/raw/lvl.xml
<?xml version="1.0" encoding="utf-8"?>
<Level>
<dimensions>
<a>5</a>
<b>5</b>
</dimensions>
.
.
.
</Level>
My java code is following
InputStream input = this.getResources().openRawResource(R.raw.lvl);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = buider.parse(input);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("dimensions");
Node node = nList.item(0);
int a = Integer.parseInt(node.getFirstChild().getNodeValue().trim());
The last line throws parsing exception, node.getNodeValue().trim() is "\t\t\n\t".

You're looking at the <dimensions> tag, not at a and b. Look:
NodeList nList = doc.getElementsByTagName("dimensions");
Node node = nList.item(0);
int a = Integer.parseInt(node.getNodeValue().trim());
You're getting the first (index 0) element of name dimensions. Not its children.
The value you see (\t\t\n\t) is what's left of dimensions' contents after children nodes are removed.

Could not understand what exactly you are trying to do ...but .. you can refer below if that helps
public class Parsing {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
Parsing parse = new Parsing();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("x.xml"));
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("dimensions");
Node node = nList.item(0);
for (Node childNode = node.getFirstChild();
childNode != null;) {
//do something
System.out.println(childNode.getNodeName());
System.out.println(childNode.getTextContent());
Node nextChild = childNode.getNextSibling();
childNode = nextChild;
}
}
}

Related

Java get tag name of a Node

I need to read a small xml file and validate it's content against a hardcoded HashMap with key= tag and value= text inside tag.
I can not get the tag name of the Node.
If I convert the Node to Element I get a cast exception.
I am reading using the DOOM classes:
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
NodeList list = doc.getElementsByTagName("MergeOptions");
if (list.getLength() == 0)
{
//throw
}
NodeList config = list.item(0).getChildNodes();
for (int i = 0; i <= config.getLength() - 1; i++)
{
Node setting = config.item(i);
String nodeName = setting.getNodeValue();
String value = setting.getTextContent();
if (defaultMergeOptions.containsKey(nodeName) == false)
{
//throw
}
if (defaultMergeOptions.get(nodeName).equals(value))
{
//throw
}
Xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MergeOptions>
<sometagName>false</sometagName>
</MergeOptions>
I am helping you with the following code structure. Once you see the tag name and the value, you can apply the logic to compare from HashMap key or value.
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Test1 {
public static void main(String[] args) throws Exception {
String xmlFile = "test.xml";
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
Element root = doc.getDocumentElement();
System.out.println(root.getNodeName());
NodeList list = root.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
System.out.println(node.getNodeName() + " : " + node.getTextContent());
}
}
}
}
I have tried to run your code, it works fine, no class cast exceptions.
Note how I used the element in the for loop the get the name, value or the existsnce of a possible children.
final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<MergeOptions>\n<sometagName>false</sometagName>\n</MergeOptions>";
final InputStream xsmlStream = new ByteArrayInputStream(xml.getBytes());
final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
final Document doc = dBuilder.parse(xsmlStream);
final NodeList nodes = doc.getElementsByTagName("MergeOptions");
for (int i = 0; i < nodes.getLength(); i++) {
final Element element = (Element) nodes.item(i);
System.out.println(element.hasChildNodes());
System.out.println(element.getNodeValue());
System.out.println(element.getTagName());
}
Using hash map is with node names as keys is a bit tricky, 'cause if your XML file have multiple node names with same names and different values, the HashMap will only store only one unique keys thus validate only one of the same name nodes. The other same name nodes but with different values will be not valid.
Well I did something diffrent.
Seems to work:
IntegrationTest.getInstance().getLogger().log(Level.INFO, "Reading merge-que file: " + xmlFile.getAbsolutePath());
try
{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
for (Entry<String, String> entry : defaultMergeOptions.entrySet())
{
String tagName = entry.getKey();
NodeList list = doc.getElementsByTagName(tagName);
if (list.getLength() != 1)
{
IntegrationTest.getInstance().getLogger().log(Level.SEVERE, TestResult.FAIL, "Merge option [{0}] has invalid content. Tag [{1}] missing or to many",
new Object[] { xmlFile.getName(), tagName });
result = TestResult.FAIL;
continue;
}
if (!defaultMergeOptions.get(tagName).equals(list.item(0).getTextContent()))
{
IntegrationTest.getInstance().getLogger().log(Level.WARNING, TestResult.FAIL, "Merge option [{0}] has diffrent content for tag [{1}].",
new Object[] { xmlFile.getCanonicalPath(), tagName });
result = TestResult.FAIL;
}
}
}
catch (Exception e)
{
IntegrationTest.getInstance().getLogger().log(Level.SEVERE, SBUtil.stackTraceToString(e.getStackTrace()));
throw new IntegrationTestException(e);
}
}

Xml parser with child elements

I have the following xml format and wanted to read the elements in java . 'm very new to xml parsing.
<string xmlns="http://tempuri.org/">
<IDV><exshowroomPrice>48800</exshowroomPrice><idv_amount>46360</idv_amount><idv_amount_min>39406</idv_amount_min><idv_amount_max>53314</idv_amount_max><exshowroomPrice_min>41480</exshowroomPrice_min><exshowroomPrice_max>56120</exshowroomPrice_max><outputmessage></outputmessage></IDV>
<string>
I have added this and after that unable to extract the elements.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(responsebuffer.toString()));
Document doc = db.parse(is);
doc.getDocumentElement().normalize();
System.out.println(doc.getDocumentElement().getTextContent());
NodeList nodes = doc.getChildNodes();
Node no1 = (Node) nodes.item(0);
if (doc.getDocumentElement().getChildNodes().getLength() > 0) {
if (nodes.item(0).getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) nodes.item(0);
NodeList nl =element.getElementsByTagName("exshowroomPrice");
System.out.println(((Node)nl).getNodeValue());
}
}
o/p:<IDV><exshowroomPrice>48800</exshowroomPrice><idv_amount>46360</idv_amount><idv_amount_min>39406</idv_amount_min><idv_amount_max>53314</idv_amount_max><exshowroomPrice_min>41480</exshowroomPrice_min><exshowroomPrice_max>56120</exshowroomPrice_max><outputmessage></outputmessage></IDV>
Kindly help,
Thanks in advance.
I'm not sure I understand your question, but your XML is malformed (it should end with ).
That said, the code to parse your document is correct, now I think the simplest way to extract individual elements would be to use class XPathAPI.
For instance:
Node node = XPathAPI.selectSingleNode(doc, "//string/IDV/exshowroomPrice");
System.out.println(node.getTextContent());
UPDATE:
Actually, XPathAPI is not a standard, but you can use XPath:
XPath xpath = XPathFactory.newInstance().newXPath();
String val = (String) xpath.evaluate("//string/IDV/exshowroomPrice/text()", doc, XPathConstants.STRING);
System.out.println(val);
Finally got the answer.
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(responsebuffer.toString()));
Document document = db.parse(is);
document.getDocumentElement().normalize();
//System.out.println(document.getDocumentElement().getTextContent());
StringBuilder xmlStringBuilder = new StringBuilder();
xmlStringBuilder.append("<?xml version=\"1.0\"?>");
xmlStringBuilder.append(document.getDocumentElement().getTextContent());
ByteArrayInputStream input = new ByteArrayInputStream(xmlStringBuilder.toString().getBytes("UTF-8"));
Document doc = db.parse(input);
NodeList nList = doc.getElementsByTagName("IDV");
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(eElement.getElementsByTagName("exshowroomPrice").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("idv_amount").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("idv_amount_min").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("idv_amount_max").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("exshowroomPrice_min").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("exshowroomPrice_max").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("outputmessage").item(0).getTextContent());
}
}
//getElementsByTagName("exshowroomPrice")
} catch (Exception e) {
e.printStackTrace();
}

Java: XML dom parsing retrieves just 1 element of the array

I have the following XML (provided by a web service)
<?xml version="1.0" encoding="UTF-8"?>
<itam>
<status>OK</status>
<data>
<item0>
<id>246</id>
<prefisso_quadrato>1</prefisso_quadrato>
<id_incontro_corrente />
<id_giornata>65</id_giornata>
<round>R1</round>
<tempo>120</tempo>
<punti_chong>0</punti_chong>
<punti_hong>0</punti_hong>
<amm_chong>0</amm_chong>
<amm_hong>0</amm_hong>
</item0>
<item1>
<id>247</id>
<prefisso_quadrato>2</prefisso_quadrato>
<id_incontro_corrente />
<id_giornata>65</id_giornata>
<round>R1</round>
<tempo>120</tempo>
<punti_chong>0</punti_chong>
<punti_hong>0</punti_hong>
<amm_chong>0</amm_chong>
<amm_hong>0</amm_hong>
</item1>
<item2>
<id>248</id>
<prefisso_quadrato>3</prefisso_quadrato>
<id_incontro_corrente />
<id_giornata>65</id_giornata>
<round>R1</round>
<tempo>120</tempo>
<punti_chong>0</punti_chong>
<punti_hong>0</punti_hong>
<amm_chong>0</amm_chong>
<amm_hong>0</amm_hong>
</item2>
</data>
</itam>
I am trying to parse it in JAVA. I can access to the <status> and also to the <data> element. But when I try to iterate over <data> items, I can read just 1 element. This is the code:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xml));
Document doc = builder.parse(is);
doc.getDocumentElement().normalize();
System.out.println(doc.getDocumentElement().getElementsByTagName("data").getLength());
OUTPUT: 1
My idea was something like the code below, but it runs just over the first element (I can read the rest element attributes and then it ends). How can I fix it? Thank you very much
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xml));
Document doc = builder.parse(is);
doc.getDocumentElement().normalize();
NodeList nodelist = doc.getDocumentElement().getElementsByTagName("data");
if(nodelist!=null){
for(int i=0; i<nodelist.getLength(); i++){
Element el = (Element) nodelist.item(i);
//use el to get data from it
}
}
The error is that you are looking for a list of <data> element and you have just one. A solution can be:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xml));
Document doc = builder.parse(is);
doc.getDocumentElement().normalize();
NodeList items = doc.getDocumentElement().getElementsByTagName("data").item(0).getChildNodes();
for(int i=0; i<items.getLength(); i++){
System.out.println(items.item(i).getNodeName());
}
Good luck!
You will have to recurively iterate over the xml file to get all the elements..
something like this
private Document getDocument(String xsdUrl)
throws ParserConfigurationException, SAXException, IOException {
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
final DocumentBuilder db = dbf.newDocumentBuilder();
final Document doc = db.parse(xsdUrl);
return doc;
}
private void processElementRecurse(final Element node) throws IOException,
ParserConfigurationException, SAXException, TransformerException {
final NodeList nl = node.getChildNodes();
for (int i = 0, n = nl.getLength(); i < n; i++) {
final Node childNode = nl.item(i);
if (childNode instanceof Element) {
}
else {
processElementRecurse(childElement);
}
}
}

getNodeName() operation on an XML node returns #text

<person>
<firstname>
<lastname>
<salary>
</person>
This is the XML I am parsing. When I try printing the node names of child elements of person,
I get
text
firstname
text
lastname
text
salary
How do I eliminate #text being generated?
Update -
Here is my code
try {
NodeList nl = null;
int l, i = 0;
File fXmlFile = new File("file.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
dbFactory.setValidating(false);
dbFactory.setIgnoringElementContentWhitespace(true);
dbFactory.setNamespaceAware(true);
dbFactory.setIgnoringComments(true);
dbFactory.setCoalescing(true);
InputStream in;
in = new FileInputStream(fXmlFile);
Document doc = dBuilder.parse(in);
doc.getDocumentElement().normalize();
Node n = doc.getDocumentElement();
System.out.println(dbFactory.isIgnoringElementContentWhitespace());
System.out.println(n);
if (n != null && n.hasChildNodes()) {
nl = n.getChildNodes();
for (i = 0; i < nl.getLength(); i++) {
System.out.println(nl.item(i).getNodeName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
setIgnoringElementContentWhitespace only works if you use setValidating(true), and then only if the XML file you are parsing references a DTD that the parser can use to work out which whitespace-only text nodes are actually ignorable. If your document doesn't have a DTD it errs on the safe side and assumes that no text nodes can be ignored, so you'll have to write your own code to ignore them as you traverse the child nodes.

Put XML element node and text node to the array of string

Please help me to put element and text nodes into an array of Strings.
For example an .xml file has:
<soap:Envelope>
<soap:Body>
<ser:getTitle>
<!--Optional:-->
<ser:title>Meeting</ser:title>
</ser:getTitle>
<ser:getDiscription>
<!--Optional:-->
<ser:discription>this is the meeting</ser:discription>
</ser:getDiscription>
...
</soap:Body>
</soap:Envelop>
Now I want to place the values into the String[] key, value as follows:
key[0] = "title";
value[0] = "meeting";
key[1] = "discription";
value[1] = "this is the meeting";
... and so on.
Many thanks in advance!
You can use DOM to parse your input XML and use something like:
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.File;
public dumpXMLTags(...) {
String[] keys; // you would need that with appropriate size initialized
String[] values;
// Parse your XML file and construct DOM tree
File fXmlFile = new File(PATH_TO_YOUR_XML_FILE);
DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
// Traverse DOM tree (make sure is not empty first, etc)
NodeIterator iterator = traversal.createNodeIterator(
doc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);
int i = 0; // index to you key/value Array
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
keys[i] = ((Element) n).getTagName();
values[i] = ((Element)n).getNodeValue();
i++;
}
}
Alternatively you could use XPATH with the
//#* | //*[not(*)]
expression, as described here: Question 7199897
public static void main(String[] args) throws Exception {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xml)));
XPathFactory xpf = XPathFactory.newInstance();
XPath xp = xpf.newXPath();
NodeList nodes = (NodeList)xp.evaluate("//#* | //*[not(*)]", doc, XPathConstants.NODESET);
System.out.println(nodes.getLength());
for (int i=0, len=nodes.getLength(); i<len; i++) {
Node item = nodes.item(i);
System.out.println(item.getNodeName() + " : " + item.getTextContent());
}
}

Categories

Resources