HI I am new to Java and trying to read an XML file.
Here is my XML file :-
<?xml version="1.0" encoding="UTF-8"?>
<parameter>
<attribute>a</attribute>
Here is my code I am trying to read the key and value from the xml but I am stuck .Here is my code :-
public class TestDBMain {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
File file = new File("ACL.xml");
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbfactory.newDocumentBuilder();
Document doc = builder.parse(file);
NodeList nList = doc.getElementsByTagName("testCaseDataName");
for(int i = 0;i<nList.getLength();i++){
Node nNode = nList.item(i);
if(nNode.getNodeType()== Node.ELEMENT_NODE){
Element ele = (Element) nNode;
// System.out.println(ele.getTextContent());
//System.out.println(ele.getElementsByTagName("testCaseName").item(0).getTextContent());
System.out.println(ele.getAttributeNode("testCaseDataName"));
//I dont know which methods to use to print the key and value in the xml under parameter
}
}
}
}
Can anyone please help me with this
Disclaimer: I maintain the JDOM project, so I am biased.... but... this is an ideal use case for JDOM:
Document doc = new SAXBuilder().build(new File("ACL.xml"));
Element root = doc.getRootElement();
for (Element testcase : root.getChildren()) {
int id = Integer.parseInt(testcase.getChildText("id"));
String name = testcase.getChildText("testCaseName");
String expect = testcase.getChildText("expectedResult");
Map<String,String> params = new LinkedHashMap<String,String>();
Element parmemt = testcase.getChild("parameter");
if (parmemt != null) {
Iterator<Element> it = parmemt.getChildren().iterator();
while (it.hasNext()) {
Element key = it.next();
if (!"key".equals(key.getName())) {
throw new IllegalStateException("Expected key but got " + key);
}
if (!it.hasNext()) {
throw new IllegalStateException("Expected value for key " + key);
}
Element val = it.next();
if (!"value".equals(val.getName())) {
throw new IllegalStateException("Expected value but got " + val);
}
params.put(key.getValue(), val.getValue());
}
}
System.out.printf("Processing test case %d -> %s\n Expect %s\n Parameters: %s\n",
id, name, expect, params.toString());
}
For me this produces the output
Processing test case 1 -> EditTest
Expect nooptionsacltrue
Parameters: {}
Processing test case 2 -> AddTest
Expect featuresaddedacltrue
Parameters: {featues=w,f}
Processing test case 3 -> AddTest
Expect duplicateacltrue
Parameters: {projectType=NEW, Name=28HPM, status=ACTIVE, canOrder=Yes}
your code read <testCaseDataName> node. it is not go inside of this tag.
so try this..
for(int i = 0;i<nList.getLength();i++){
NodeList nodeList = nList.item(i).getChildNodes();
for(int j = 0;j<nList.getLength();j++){
Node nNode = nodeList.item(j);
if(nNode.getNodeType()== Node.ELEMENT_NODE){
System.out.println(nNode.getNodeName() +" : "+nNode.getTextContent());
if(nNode.getNodeName().equals("parameter")){
NodeList param = nNode.getChildNodes();
System.out.println(" "+param.item(0).getNodeName() +" : "+param.item(0).getTextContent());
System.out.println(" "+param.item(1).getNodeName() +" : "+param.item(1).getTextContent());
}
}
}
}
Related
I have an XML file as below. I want to get its specific child tag from the parent tag using java.
<?xml version="1.0"?>
<class>
<question id="scores">
<ans>12</ans>
<ans>32</ans>
<ans>44</ans>
</question>
<question id="ratings">
<ans>10</ans>
<ans>22</ans>
<ans>45</ans>
<ans>100</ans>
</question>
<default>
Sorry wrong
</default>
</class>
i want the function to be like this
String function(String id)
it will return the ans tag randomly
i.e if I give input id=scores, the program will look in the XML tag for scores as id and get length()of its children, in this case, 3, then retun randomly like 32 or 44 or 12.if id is not present, return default.
my code so far
public class ChatBot {
private String filepath="E:\\myfile.xml";
private File file;
private Document doc;
public ChatBot() throws SAXException, IOException, ParserConfigurationException {
file = new File("E:\\myfile.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(file);
}
String Function(String id){
// This part
return null;
}
}
As suggested by #LMC (because of org.w3c.dom.Document.getElementById() not recognizing arbitrary id attributes as IDs for getElementById() or as a browser would, mostly for HTML semantics/format), maybe:
String Function(String id) throws XPathExpressionException {
XPath xPath = XPathFactory.newInstance().newXPath();
// Be aware: id inserted without any escaping!
NodeList parents = (NodeList)xPath.evaluate("/class/question[#id='" + id + "']", doc, XPathConstants.NODESET);
if (parents.getLength() < 1) {
return null;
} else if (parents.getLength() > 1) {
// Huh, duplicates?
}
Element parent = (Element)parents.item(0);
NodeList children = parent.getChildNodes();
List<Element> answers = new ArrayList<Element>();
for (int i = 0, max = children.getLength(); i < max; i++) {
if (children.item(i).getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if (children.item(i).getNodeName().equals("ans") != true) {
// Huh?
continue;
}
answers.add((Element)children.item(i));
}
if (answers.size() <= 0) {
return null;
}
int selection = (int)(Math.random() * answers.size());
return answers.get(selection).getTextContent();
}
I did some codes but they are not working. I also need to validate if a header:message exists
String xml = "<header:HostError>
<header:message>
<header:messageCode>321</header:messageCode>
<header:message>test</header:message>
</header:message>
<header:message>
<header:messageCode>123</header:messageCode>
<header:message>test</header:message>
</header:message>
</header:HostError>"
How do I get the first messageCode and message?
private void extractErrorsFromResponse(SOAPFaultDetail faultResponse) {
for (Iterator itr = faultResponse.getAllDetailEntries(); itr.hasNext(); ) {
Object element = itr.next();
if (element instanceof OMElement) {
Object code = ((OMElement) element).getFirstChildWithName(new QName("message")).getFirstChildWithName(new QName("messageCode"));
Object message = ((OMElement) element).getFirstChildWithName(new QName("message")).getFirstChildWithName(new QName("message"));
faultResponse.addDetailEntry(((OMElement) element).cloneOMElement());
}
}
}
A quick solution would be that.
String xml = "<header:HostError>" +
"<header:message>\n" +
"<header:messageCode>321</header:messageCode>\n" +
"<header:message>test</header:message>\n" +
"</header:message>\n" +
"<header:message>\n" +
"<header:messageCode>123</header:messageCode>\n" +
"<header:message>test</header:message>\n" +
"</header:message>\n" +
"</header:HostError>";
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new InputSource(new StringReader(xml)));
NodeList list = doc.getElementsByTagName("header:messageCode");
System.out.println("First messageCode : " + list.item(0).getFirstChild().getNodeValue());
NodeList list_ = doc.getElementsByTagName("header:message");
System.out.println("First message : " + list_.item(1).getFirstChild().getNodeValue());
It prints,
First messageCode : 321
First message : test
Based on that, you need to find a more generic method.
I am attempting to get the text from an xml node. The code seems to recognize the node. This code
String L = "Node Length: " + nList.getLength()+ " Text: " + nList.item(0).toString();
jTextArea1.setText(L);
returns: Node Length: 1 Text: [CompanyName: null]
So it seems like the code is finding the node but not getting the value. Here is the whole code block (this is my first time posting so I hope I formatted this right!). the FOR loop should grab the value but is throwing a NULL Pointer Exception:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try{
//Get Document Builder
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//Build Document
Document xdocument = builder.parse(new File("request.xml"));
xdocument.getDocumentElement().normalize();
NodeList nList = xdocument.getElementsByTagName("CompanyName");
//String L = "Node Length: " + nList.getLength()+ " Text: " + nList.item(0).toString();
//jTextArea1.setText(L);
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node node = nList.item(0);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element eElement = (Element) node;
String nodetxt= "Company : " + eElement.getElementsByTagName("CompanyName").item(0).getTextContent() ;
jTextArea1.setText(nodetxt) ;
}
}
} catch (Exception ex) {
java.util.logging.Logger.getLogger(TechKnowPOSGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
}
and here is the XML file:
<?xml version="1.0" encoding="utf-8"?>
<RunReportQueryAction xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CompanyName>Techknow</CompanyName>
<IntegrationLoginId>cwapitest</IntegrationLoginId>
<IntegrationPassword>cwtest123</IntegrationPassword>
<ReportName>Company</ReportName>
<!-- <Conditions></Conditions> -->
<!-- <Limit>10</Limit> -->
<!-- <Skip></Skip> -->
<!-- <OrderBy></OrderBy> -->
</RunReportQueryAction>
Any help is greatly appreciated.
On this line you get all the CompanyName elements:
NodeList nList = xdocument.getElementsByTagName("CompanyName");
Then you loop through them in your for loop and call this:
eElement.getElementsByTagName("CompanyName")
But that would imply that the CompanyName has nested CompanyName elements, which it does not. Therefore you should use this in your for loop, as the elements you are iterating are already the CompanyName elements:
String nodeTxt = "Company : " + eElement.getTextContent()
I'm looking for ways to read a generic xml file
Here is an example of a normal xml file
<?xml version="1.0"?>
<students>
<student>
<name>John</name>
<grade>B</grade>
<age>12</age>
</student>
<student>
<name>Mary</name>
<grade>A</grade>
<age>11</age>
</student>
<student>
<name>Simon</name>
<grade>A</grade>
<age>18</age>
</student>
</students>
and here is example of a typical xml parser that would read that code and print it out
public class XMLParser {
public void getAllUserNames(String fileName) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File(fileName);
if (file.exists()) {
Document doc = db.parse(file);
Element docEle = doc.getDocumentElement();
// Print root element of the document
System.out.println("Root element of the document: "
+ docEle.getNodeName());
NodeList studentList = docEle.getElementsByTagName("student");
// Print total student elements in document
System.out
.println("Total students: " + studentList.getLength());
if (studentList != null && studentList.getLength() > 0) {
for (int i = 0; i < studentList.getLength(); i++) {
Node node = studentList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out
.println("=====================");
Element e = (Element) node;
NodeList nodeList = e.getElementsByTagName("name");
System.out.println("Name: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
nodeList = e.getElementsByTagName("grade");
System.out.println("Grade: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
nodeList = e.getElementsByTagName("age");
System.out.println("Age: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
}
}
} else {
System.exit(1);
}
}
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
XMLParser parser = new XMLParser();
parser.getAllUserNames("c:\\test.xml");
}
}
This code needs lines like this
NodeList studentList = docEle.getElementsByTagName("student");
NodeList nodeList = e.getElementsByTagName("name");
In order to work correctly.
My questions comes from how would I make that generic. Is there any way where I could read that same XML file without having to get specific elements by tagNames and yet still print it out in a view able format.
In the above example you are using Dom parser. By using Jaxb Context unmarshaller you can convert the xml to java object, then you can achive your task.
You need to have a generic function to handle.
Generic function is as follows:
/* Prints the Node Value */
public void PrintNodeValue(Element element, String tagName, String msg)
{
NodeList nodeList = element.getElementsByTagName(tagName);
System.out.println(msg + nodeList.item(0).getChildNodes().item(0).getNodeValue());
}
Function is called as below:
PrintNodeValue(e, "name", "Name: ");
PrintNodeValue(e, "grade", "Grade: ");
I have this project I'm working on where I want to parse an xml file that looks like this:
<?xml version='1.0' encoding='UTF-8'?>
<projectlist>
<project>
<name>SuperDuperApp</name>
<type>batch</type>
<prod>
<server>testserver01</server>
</prod>
<qa>
<server>testserver01</server>
</qa>
<dev>
<server>testserver01</server>
</dev>
</project>
<project>
<name>Calculator</name>
<type>deploy</type>
<prod>
<server>testserver02</server>
<server>testserver03</server>
<server>testserver04</server>
</prod>
<qa>
<server>testserver05</server>
<server>testserver06</server>
<server>testserver07</server>
</qa>
<dev>
<server>testserver12</server>
<server>testserver13</server>
<server>testserver14</server>
</dev>
</project>
</projectlist>
With this method parsing the file and trying to print out in the format:
name: SuperDuperApp
type: batch
server: testserver01
name: Calculator
type: deploy
environment: dev
server: testserver12
server: testserver13
server: testserver14
etc.
public void parseXML() {
ArrayList al = new ArrayList();
HashSet hs = new HashSet();
try {
InputStream file = this.getClass().getResourceAsStream(
"/net/swing/sandbox/util/config/projectlist.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
doc.getDocumentElement().normalize();
System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("project");
System.out.println("Information of all servers...");
for (int i=0;i<nList.getLength();i++){
Node fstNode = nList.item(i);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElement = (Element) fstNode;
NodeList nameElementList = fstElement.getElementsByTagName("name");
Element nameElement = (Element) nameElementList.item(0);
NodeList name = nameElement.getChildNodes();
System.out.println("project name: " + ((Node) name.item(0)).getNodeValue());
hs.add(((Node) name.item(0)).getNodeValue());
NodeList typeElementList = fstElement.getElementsByTagName("type");
Element typeElement = (Element) typeElementList.item(0);
NodeList type = typeElement.getChildNodes();
System.out.println("Deploy type: " + ((Node) type.item(0)).getNodeValue());
//print out server list can't do it for some reason
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
al.clear();
al.addAll(hs);
Collections.sort(al);
for (int z = 0; z < al.size(); z++) {
listModel.addElement(al.get(z));
}
} catch (Exception e) {
e.printStackTrace();
}
lstProject.validate();
}
So I rewrote my method and now I'm just stuck <---newb
Check the documentation for Node. Each node has a method getChildNodes. Check that for the existence of children nodes and than iterate over them like you are doing.
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.
I think it's appropriate to use XSLT transform in your case (much less boilerplate code) Look at TransformerFactory and java api for xml processing.
As a q&d solution you could apply the same strategy as for getting "project" node:
...
System.out.println("servers:");
NodeList sList = eElement.getElementsByTagName("server");
for (int i = 0; i < sList.getLength(); i++) {
String stuff = sList.item(i).getFirstChild().getNodeValue();
System.out.println(stuff);
}