I am struggling to get the data out of the following XML node. I use DocumentBuilder to parse XML and I usually get the value of a node by defining the node but in this case I am not sure how the node would be.
<Session.openRs status="success" sessionID="19217B84:AA3649FE:B211FF37:E61A78F1:7A35D91D:48E90C41" roleBasedSecurity="1" entityID="1" />
This is how I am getting the values for other tags by the tag name.
public List<NYProgramTO> getNYPPAData() throws Exception {
this.getConfiguration();
List<NYProgramTO> to = dao.getLatestNYData();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document document = null;
// Returns chunkSize
/*List<NYProgramTO> myList = getNextChunk(to);
ExecutorService executor = Executors.newFixedThreadPool(myList.size());
myList.stream().parallel()
.forEach((NYProgramTO nyTo) ->
{
executor.execute(new NYExecutorThread(nyTo, migrationConfig , appContext, dao));
});
executor.shutdown();
executor.awaitTermination(300, TimeUnit.SECONDS);
System.gc();*/
try {
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource source = new InputSource();
for(NYProgramTO nyProgram: to) {
String reqXML = nyProgram.getRequestXML();
String response = RatingRequestProcessor.postRequestToDC(reqXML, URL);
// dao.storeData(nyProgram);
System.out.println(response);
if(response != null) {
source.setCharacterStream(new StringReader(response));
document = builder.parse(source);
NodeList list = document.getElementsByTagName(NYPG3Constants.SERVER);
for(int iterate = 0; iterate < list.getLength(); iterate++){
Node node = list.item(iterate);
if(node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
nyProgram.setResponseXML(response);
nyProgram.setFirstName(element.getElementsByTagName(NYPG3Constants.F_NAME).item(0).getTextContent());
nyProgram.setLastName(element.getElementsByTagName(NYPG3Constants.L_NAME).item(0).getTextContent());
nyProgram.setPolicyNumber(element.getElementsByTagName(NYPG3Constants.P_NUMBER).item(0).getTextContent());
nyProgram.setZipCode(element.getElementsByTagName(NYPG3Constants.Z_CODE).item(0).getTextContent());
nyProgram.setDateOfBirth(element.getElementsByTagName(NYPG3Constants.DOB).item(0).getTextContent());
nyProgram.setAgencyCode(element.getElementsByTagName(NYPG3Constants.AGENCY_CODE).item(0).getTextContent());
nyProgram.setLob(element.getElementsByTagName(NYPG3Constants.LINE_OF_BUSINESS).item(0).getTextContent());
if(element.getElementsByTagName(NYPG3Constants.SUBMISSION_NUMBER).item(0) != null){
nyProgram.setSubmissionNumber(element.getElementsByTagName(NYPG3Constants.SUBMISSION_NUMBER).item(0).getTextContent());
} else {
nyProgram.setSubmissionNumber("null");
}
I need to get the value for sessionId. What I want to know is the node, I am sure it can't be .I am retrieving the values via tag names so what would be the tag name in this case?
Thanks in advance
You should consider using XPath. At least for me, is so much easy to use and, in your case, in order to get sessionID you could try something like this:
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/Session.openRs/#sessionID";
String sessionID = xPath.evaluate(expression,document);
You can obtain 'document' like this:
Document document = builder.newDocumentBuilder();
Hope this can help!!
Related
I am trying to parse an XML file into JSON. While I am able to parse successfully using a HashMap, the XML file I am using has a lot of irrelevant information which also gets reflected in the JSON.
My XML file is a topology file, basically topology for network elements and their respective processes. So, it is divided into parent and child nodes. Most of the relevant information I seek lie with the parent nodes and I want to disregard the child nodes by whatever means, so that only the parent nodes are available in the JSON.
Here's the code I wrote to parse. I have tried to write code to get child enter code herenodes but I can't figure out how to remove them(like what conditions I can use):
static String nodeType1,nodeType;
static String nodeName1,nodeName;
static String nodeIP1,nodeIP;
public static void main(String[] args) {
try { File fXmlFile = new File("SystemTopology.txt");
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("SNOSNE") ;
Map<String, Object> data = new HashMap<String, Object>();
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
Element el = (Element) nNode;
nodeType = el.getAttribute("snostype");
nodeName = el.getAttribute("cimname");
nodeIP = el.getAttribute("snoshostip");
NodeList list = el.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node nNode1 = list.item(i);
if(list.item(i).getNodeType() == Node.ELEMENT_NODE){
Element element = (Element) list.item(i);
nodeType1 = element.getAttribute("snostype");
nodeName1 = element.getAttribute("cimname");
nodeIP1 = element.getAttribute("snoshostip");
if(!nodeIP1.isEmpty()) {
System.out.println(nodeType1);
System.out.println(nodeName1);
System.out.println(nodeIP1);
}
}
}
//Need to add conditions here that would get only child nodes
if(!nodeIP.isEmpty()) {
data.put(nodeName, nodeType+","+nodeIP);
}
}
JSONObject json = new JSONObject(data);
System.out.printf( "JSON: %s", json.toString(2));
}
catch (Exception excp)
{
System.out.println("topology file not found " + excp.getMessage());
}
Topology file looks like:
<SNOSNE cimname="EDA_01" snoshostip="1.1.1.1" snostype="EDA">
<SNOSNE cimname="Resources" snoshostip="1.1.1.1" snostype="EDA">
</SNOSNE>
<SNOSNE cimname="CPU" snoshostip="1.1.1.1" snostype="EDA">
</SNOSNE>
...
...
...
</SNOSNE>
Expected output needs to contain only the parent with cimname="EDA_01". And all child nodes need to be disregarded in JSON output.
We are building a WebSite that is 100% data driven. All possible field names will be in PostgreSQL and all values for those fields are coming from a Web Service. The end user will have the ability to build their own page, by clicking on fields that they want on their screen. I'm trying to come up with the best way to have the text field in PostgreSQL to relay the full mapping in the XML data that's coming back from the Web Service. Should I use root\property1\subproperty and just have something loop through breaking it down from XML or is there a more effective way?
EDIT: Replaced JSON with XML. I've been working with JSON so much lately, I misspoke and said JSON, when these REST Web Services return XML.
EDIT2: I found kind of a solution, but as you can see in the below example, if the node name exists twice, then it will return as two nodes. I need to figure out if I should stored in DB as newnode2\firstName, I then should loop through nodes, looking for newnode2 first, then looping through to find firstName. I remember many years ago using an XML object in .NET were I could just do something like a #nodex\subnode and get values.. I might be thinking to hard here.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = null;
try
{
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse( new InputSource( new StringReader( "<response><responseStatus>Success</responseStatus><dataSet name=\"myvalue\"><newnode><firstName>John</firstName><lastName>Smith</lastName></newnode><newnode2><firstName>Bob</firstName><birthDate>11/11/1965</birthDate></newnode2></dataSet></response>" )) );
NodeList nList = doc.getElementsByTagName("firstName");
Node n;
String value;
for(int i=0; i<nList.getLength(); i++)
{
n = nList.item(i);
value = n.getTextContent();
}
} catch (Exception e) {
e.printStackTrace();
}
Ok, I came up with a recursive function. Please let me know if you see or know of a better way
String xml = "<response><responseStatus>Success</responseStatus><dataSet name=\"myvalue\"><newnode><firstName>John</firstName><lastName>Smith</lastName></newnode><newnode2><firstName>Bob</firstName><birthDate>11/11/1965</birthDate></newnode2></dataSet></response>";
String value;
value = getXMLValue(xml, "newnode2/firstName"); //example of multi-node
value = getXMLValue(xml, "birthDate"); //example of going directly to field if it's the only node with that name.
value = getXMLValue(xml, "dataSet/name"); //example of getting attribute
Functions:
public String getXMLValue(String xml, String searchNodes) {
String retVal = "";
String[] nodeSplit = searchNodes.split("/");
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc;
NodeList nList;
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse( new InputSource( new StringReader( xml )) );
nList = doc.getElementsByTagName(nodeSplit[0]);
retVal = GetNode(nList, searchNodes, 0);
} catch (Exception e) {
e.printStackTrace();
}
return retVal;
}
public String GetNode(NodeList nl, String searchNodes, int item)
{
String retVal = null;
String findNode = searchNodes.split("/")[item];
int count = searchNodes.split("/").length;
item++;
for(int i=0; i<nl.getLength(); i++) {
String foundNode = nl.item(i).getNodeName();
NamedNodeMap nnm = nl.item(i).getAttributes();
if(nnm!=null && nnm.getLength()>0 && count>item) {
Node attribute = nnm.getNamedItem(searchNodes.split("/")[item]);
if(attribute!=null) {
retVal = attribute.getTextContent();
break;
}
}
if(foundNode.equals(findNode) && count>item) {
retVal = GetNode(nl.item(i).getChildNodes(), searchNodes, item);
break;
} else if(foundNode.equals(findNode) && count==item) {
retVal = nl.item(i).getTextContent();
break;
}
}
return retVal;
}
I need to get value like "Symbol" ect. from xml file and send to list.
For now my code looks like this:
Scanner sc = null;
byte[] buff = new byte[1 << 13];
List<String> question2 = new ArrayList<String>();
question2 = <MetodToGetFile>(sc,fileListQ);
for ( String strLista : question2){
ByteArrayInputStream in = new ByteArrayInputStream(strLista.getBytes());
try(InputStream reader = Base64.getMimeDecoder().wrap(in)){
try (GZIPInputStream gis = new GZIPInputStream(reader)) {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()){
int readGis = 0;
while ((readGis = gis.read(buff)) > 0)
out.write(buff, 0, readGis);
byte[] buffer = out.toByteArray();
String s2 = new String(buffer);
}
}
}
}
}
I want to know how can i contunue this and takevalue "xxx" and "zzzz" to put to another list, because i need to compere some value.
XML looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Name Name="some value">
<Group Names="some value">
<Package Guid="{7777-7777-7777-7777-7777}">
<Attribute Typ="" Name="Symbol">xxx</Attribute>
<Attribute Type="" Name="Surname">xxx</Attribute>
<Attribute Type="Address" Name="Name">zzzz</Attribute>
<Attribute Type="Address" Name="Country">zzzz</Attribute>
</Package>
EDIT: Hello i hope that my solution will be usefull for someone :)
try{
//Get is(inputSource with xml in s2(xml string value from stream)
InputSource is = new InputSource(new StringReader(s2));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
//Get "some value" from attribut Name
String name= (String) xpath.evaluate("/Name/#Name", doc, XPathConstants.STRING);
//Get "guid" from attribute guid
String guid= (String) xpath.evaluate("/Name/Group/Package/#Guid", doc, XPathConstants.STRING);
//Get element xxx by tag value Symbol
String symbol= xpath.evaluate("/Name/Group/Package/Attribute[#Name=\"Symbol\"]", doc.getDocumentElement());
System.out.println(name);
System.out.println(guid);
System.out.println(symbol);
}catch(Exception e){
e.printStackTrace();
}
I would be happy if i will help someone by my code :)
Add a method like this to retrieve all of the elements that match a given Path expression:
public List<Node> getNodes(Node sourceNode, String xpathExpresion) throws XPathExpressionException {
// You could cache/reuse xpath for better performance
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate(xpathExpresion,sourceNode,XPathConstants.NODESET);
ArrayList<Node> list = new ArrayList<Node>();
for(int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
list.add(node);
}
return list;
}
Add another method to build a Document from an XML input:
public Document buildDoc(InputStream is) throws Exception {
DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = fact.newDocumentBuilder();
Document newDoc = parser.parse(is);
newDoc.normalize();
is.close();
return newDoc;
}
And then put it all together:
InputSource is = new InputSource(new StringReader("... your XML string here"));
Document doc = buildDoc(is);
List<Node> nodes = getNodes(doc, "/Name/Group/Package/Attribute");
for (Node node: nodes) {
// for the text body of an element, first get its nested Text child
Text text = node.getChildNodes().item(0);
// Then ask that Text child for it's value
String content = node.getNodeValue();
}
I hope I copied and pasted this correctly. I pulled this from a working class in an open source project of mine and cleaned it up a bit to answer your specific question.
Need to convert the format of output to UTF-8, because the output is not treating special characters.
Anyone have any idea how can this be done?
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
URL u = new URL("http://www.aredacao.com.br/tv-saude");
Document doc = builder.parse(u.openStream());
NodeList nodes = doc.getElementsByTagName("item");`
The problem is that the site returns <?xml version='1.0' encoding='iso-8859-1'?> but it should be returning <?xml version='1.0' encoding='UTF-8'?>.
One solution is to translate each element's text yourself:
static void readData()
throws IOException,
ParserConfigurationException,
SAXException {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
URL u = new URL("http://www.aredacao.com.br/tv-saude");
Document doc = builder.parse(u.toString());
NodeList nodes = doc.getElementsByTagName("item");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Element el = (Element) node;
String title =
el.getElementsByTagName("title").item(0).getTextContent();
title = treatCharsAsUtf8Bytes(title);
String description =
el.getElementsByTagName("description").item(0).getTextContent();
description = treatCharsAsUtf8Bytes(description);
System.out.println("title=" + title);
System.out.println("description=" + description);
System.out.println();
}
}
private static String treatCharsAsUtf8Bytes(String s) {
byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
return new String(bytes, StandardCharsets.UTF_8);
}
Another possibility is to write a subclass of FilterInputStream which replaces the erroneous <?xml prolog's encoding, but that is a lot more work, and I would only consider doing that if the document had a complex structure with many different elements such that translating each would be unwieldy.
I'm stumped, hopefully I've just done a dumb thing that I can fix easily.
I'm passing in a String full of XML, being 'XMLstring'. I want to get one of the elements and print the child nodes in a "name = value" on the console. The problem is that the console keeps printing garbage along with the element name that I cannot work out how to get rid of.
Anyway, this code:
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(XMLstring));
Document doc = db.parse(is);
NodeList nodes = doc.getElementsByTagName("client-details");
Node node = nodes.item(0);
NodeList client_details = node.getChildNodes();
for (int i = 0; i < client_details.getLength(); i++) {
System.out.println(client_details.item(i).getNodeName()+" = "+getTextContents(client_details.item(i)));
}
}
catch (Exception e) {
e.printStackTrace();
}
Gives me the following:
#text =
testing-mode = false
#text =
name = testman
#text =
age = 30
Why is it printing the "#text ="? How do I get rid of it?
I am using NetBeans if that helps.
You want to use getNodeValue() instead:
System.out.println(client_details.item(i).getNodeValue()+" = "+getTextContents(client_details.item(i)));
If you look in the table at the top of this page, you see that for Text nodes, getNodeName() returns #text.
I am curious to see what each of the two function calls in your System.out.println() is printing out separately, only because the entire output should be on one line. One of those two is causing the problems, and i believe it may be internal to the function.
Otherwise, if you use String splitString = string.split("[=]"); it will split up the line based on the delimeter '='
then you can
String splitString = string.split("[=]");
System.out.println(splitString[1] + " = " + splitString[2]);
or, much more simply, make that one small edit that #retrodrone posted
OK I managed to resolve this issue, for anyone else who cares. The problem with the code is that the Node needs to be cast to an Element before you can get the tag name out of it in this manner. Therefore:
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(XMLstring));
Document doc = db.parse(is);
NodeList nodes = doc.getElementsByTagName("client-details");
Node node = nodes.item(0);
NodeList client_details = node.getChildNodes();
Element elementary;
for (int i = 0; i < client_details.getLength(); i++) {
if(client_details.item(i).getNodeType() == Node.ELEMENT_NODE) {
elementary = (Element) client_details.item(i);
System.out.println(elementary.getTagName()+" = "+getTextContents(client_details.item(i)));
}
}
}
Which produces the desired result, minus that "#text" bollocks :)
testing-mode = false
name = testman
age = 30
Notice the new "if" statement I added inside the for loop and the cast of the node to an element before calling getNodeName, which does work for Elements.