Represent Null values as blank in xml with java - java

My Excel data values are:
Name EmployeeId Address Phone
Rony FBL123 Dhaka 12333333
Azam FBL321 Dhaka 67778888
Rony Chandpur 099776655
Azam 9988
Here is my code to read a list of data values including null values:
And convert data into xml:
try {
DocumentBuilderFactory dFact = DocumentBuilderFactory.newInstance();
DocumentBuilder build = dFact.newDocumentBuilder();
Document doc = build.newDocument();
Element root = doc.createElement("dataroot");
doc.appendChild(root);
Element Details = doc.createElement("DATA");
root.appendChild(Details);
for(int i=0; i<list.size()-2; i +=3 ) {
Element name = doc.createElement("Name");
name.appendChild(doc.createTextNode(String.valueOf(list.get(i))));
Details.appendChild(name);
Element id = doc.createElement("Empid");
id.appendChild(doc.createTextNode(String.valueOf(list.get(i+1))));
Details.appendChild(id);
Element ad = doc.createElement("Add");
ad.appendChild(doc.createTextNode(String.valueOf(list.get(i+2))));
Details.appendChild(ad);
Element mo = doc.createElement("Mobile");
mo.appendChild(doc.createTextNode(String.valueOf(list.get(i+3))));
Details.appendChild(mo);
}
Here where i need to check the data is null or not and how to handle it.

You should ideally be doing this where you add the element in your list using add(). This part of code snippet is however NOT on your post above.
Assuming list is defined as ArrayList<String> and val is of String type, you can do something like:
if (val == null) {
list.add("");
}
else {
list.add(val);
}

Related

Java: Get sum of child node values in a nested xml file

I need to make a program which outputs the price of a specific element in an xml file.
The xml file looks like this:
<list name="root">
<book name="B1" price="30" isbn="123"/>
<list name="L1">
<book name="B2" price="20" isbn="234"/>
<list name="L2">
<cd name="C1" price="15"/>
<cd name="C2" price="5"/>
<book name="B3" price="10" isbn="345"/>
</list>
<cd name="C3" price="15"/>
<book name="B4" price="60" isbn="456"/>
</list>
</list>
My program should output something like this:
getPrice(B1) = 30;
getPrice(L1) = B2+L2+C3+B4 = 125 ...
My idea is to store the names and values in a hashmap, and then get the values from it. But, I have troubles getting the price for the nested lists. The program should work for different xml files as well. Only the types (cd, book and list) will be the same.
Here is my code so far:
public class ManageList implements Assignment7 {
private HashMap<String, Double> data = new HashMap<String, Double>();
#Override
public void loadXml(File input) throws Exception {
// given in the readme
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// get filename => absolute path
String filename = input.getAbsolutePath();
Document doc = db.parse(new File(filename));
// Normalize the XML Structure
doc.getDocumentElement().normalize();
// get the root element from XML document
// Element root = doc.getDocumentElement();
// ####################################
// acces elements and their attributes and store it in a hashmap
// ####################################
NodeList nl = doc.getElementsByTagName("*");
storeNodes(nl);
//System.out.println(Arrays.asList(data));
}
#Override
public Optional<Double> getPrice(String item) {
return null;
}
public void storeNodes(NodeList nl) {
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
int type = n.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element e = (Element) n;
if (e.getTagName() == "book" || e.getTagName() == "cd") {
data.put(e.getAttribute("name"), Double.parseDouble(e.getAttribute("price")));
}
if (e.getTagName() == "list" && n.hasChildNodes()) {
String name = e.getAttribute("name");
//here i get a NumberFormatException
//data.put(name, Double.parseDouble(e.getAttribute("price")));
//just to show output
data.put(name, 0.0);
}
storeNodes(n.getChildNodes());
}
}
}
Hashmap output:
[{B2=20.0, C3=15.0, B3=10.0, B4=60.0, L1=0.0, L2=0.0, root=0.0, C1=15.0, B1=30.0, C2=5.0}]
How can I get the values for the nested Lists?
Thank you!
Since list contains sub attributes, looping from nList.getLength()-1 to 0 will avoid so many problems.
For list we need values(prices) of sub attributes book and cd. So looping from last to first will help us in storing the values of sub attributes in data as a prior step.
Now, For us to get total price of list, we iterate all over NodeList of books and cd.
we sum up all the values which makes the price of the list.
Below is the code if (e.getTagName() == "list" && n.hasChildNodes(),
NodeList books = e.getElementsByTagName("book");
NodeList cd = e.getElementsByTagName("cd");
System.out.println(books.getLength());
System.out.println(cd.getLength());
double listPrice = 0;
for(int i=0;i<books.getLength();i++) {
Node t = books.item(i);
Element e1 = (Element)t;
/**This can be reduced if we loop from nList.getLength()-1 to 0, Since the data already exists in data.
//if (!data.containsKey(e1.getAttribute("name"))){
// data.put(e1.getAttribute("name"),Double.parseDouble(e1.getAttribute("price")));
//
//}
*/
listPrice += Double.parseDouble(e1.getAttribute("price"));
}
for(int i=0;i<cd.getLength();i++){
Node t = cd.item(i);
Element e1 = (Element)t;
listPrice += Double.parseDouble(e1.getAttribute("price"));
}
for any doubts - comment.
Thanks.

navigating hierarchy of xml input file

How do I list the element names at a given level in an xml schema hierarchy? The code I have below is listing all element names at every level of the hierarchy, with no concept of nesting.
Here is my xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="CDA.xsl"?>
<SomeDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:something">
<title>some title</title>
<languageCode code="en-US"/>
<versionNumber value="1"/>
<recordTarget>
<someRole>
<id extension="998991"/>
<addr use="HP">
<streetAddressLine>1357 Amber Drive</streetAddressLine>
<city>Beaverton</city>
<state>OR</state>
<postalCode>97867</postalCode>
<country>US</country>
</addr>
<telecom value="tel:(816)276-6909" use="HP"/>
</someRole>
</recordTarget>
</SomeDocument>
Here is my java method for importing and iterating the xml file:
public static void parseFile() {
//get the factory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
//parse using builder to get DOM representation of the XML file
Document dom = db.parse("D:\\mypath\\somefile.xml");
//get the root element
Element docEle = dom.getDocumentElement();
//get a nodelist of elements
NodeList nl = docEle.getElementsByTagName("*");
if (nl != null && nl.getLength() > 0) {
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println("node.getNodeName() is: "+node.getNodeName());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
The output of the above program is:
title
languageCode
versionNumber
recordTarget
someRole
id
addr
streetAddressLine
city
state
postalCode
country
telecom
Instead, I would like to output the following:
title
languageCode
versionNumber
recordTarget
It would be nice to then be able to list the children of recordTarget as someRole, and then to list the children of someRole as id, addr, and telecom. And so on, but at my discretion in the code. How can I change my code to get the output that I want?
You're getting all nodes with this line:
NodeList nl = docEle.getElementsByTagName("*");
Change it to
NodeList nl = docEle.getChildNodes();
to get all of its children. Your print statement will then give you the output you're looking for.
Then, when you iterate through your NodeList, you can choose to call the same method on each Node you create:
NodeList children = node.getChildNodes();
If you want to print an XML-like structure, perhaps a recursive method that prints all child nodes is what you are looking for.
You could re-write the parseFile (I'd rather call it parseChildrenElementNames) method to take an input String that specifies the element name for which you want to print out its children element names:
public static void parseChildrenElementNames(String parentElementName) {
// get the factory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
// Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
// parse using builder to get DOM representation of the XML file
Document dom = db
.parse("D:\\mypath\\somefile.xml");
// get the root element
NodeList elementsByTagName = dom.getElementsByTagName(parentElementName);
if(elementsByTagName != null) {
Node parentElement = elementsByTagName.item(0);
// get a nodelist of elements
NodeList nl = parentElement.getChildNodes();
if (nl != null) {
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println("node.getNodeName() is: "
+ node.getNodeName());
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
However, this will only consider the first element that matches the specified name.
For example, to get the list of elements under the first node named someRole, you would call parseChildrenElementNames("someRole"); which would print out:
node.getNodeName() is: id
node.getNodeName() is: addr
node.getNodeName() is: telecom

JSoup parsing data from within a tag

I am managing to parse most of the data I need except for one as it is contained within the a href tag and I am needing the number that appears after "mmsi="
Sunsail 4013
my current parser fetches all the other data I need and is below. I tried a few things out the code commented out returns unspecified occasionally for an entry. Is there any way I can add to my code below so that when the data is returned the number "235083844" returns before the name "Sunsail 4013"?
try {
File input = new File("shipMove.txt");
Document doc = Jsoup.parse(input, null);
Elements tables = doc.select("table.shipInfo");
for( Element element : tables )
{
Elements tdTags = element.select("td");
//Elements mmsi = element.select("a[href*=/showship.php?mmsi=]");
// Iterate over all 'td' tags found
for( Element td : tdTags ){
// Print it's text if not empty
final String text = td.text();
if( text.isEmpty() == false )
{
System.out.println(td.text());
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Example of data parsed and html file here
You can use attr on an Element object to retrieve a particular attribute's value
Use substring to get the required value if the String pattern is consistent
Code
// Using just your anchor html tag
String html = "Sunsail 4013";
Document doc = Jsoup.parse(html);
// Just selecting the anchor tag, for your implementation use a generic one
Element link = doc.select("a").first();
// Get the attribute value
String url = link.attr("href");
// Check for nulls here and take the substring from '=' onwards
String id = url.substring(url.indexOf('=') + 1);
System.out.println(id + " "+ link.text());
Gives,
235083844 Sunsail 4013
Modified condition in your for loop from your code:
...
for (Element td : tdTags) {
// Print it's text if not empty
final String text = td.text();
if (text.isEmpty() == false) {
if (td.getElementsByTag("a").first() != null) {
// Get the attribute value
String url = td.getElementsByTag("a").first().attr("href");
// Check for nulls here and take the substring from '=' onwards
String id = url.substring(url.indexOf('=') + 1);
System.out.println(id + " "+ td.text());
}
else {
System.out.println(td.text());
}
}
}
...
The above code would print the desired output.
If you need value of attribute, you should use attr() method.
for( Element td : tdTags ){
Elements aList = td.select("a");
for(Element a : aList){
String val = a.attr("href");
if(StringUrils.isNotBlank(val)){
String yourId = val.substring(val.indexOf("=") + 1);
}
}

Get the list of values using dom parser in android

I have to develop an android application.
Here i have follows following xml format.
<Product>
<product name="viki" productid="111">
<ProductType>
<producttype>Nokia</producttype>
<producttype>Samsung</producttype>
</ProductType>
</product>
</Product>
Here i have to get the producttype for particluar product.so i have wrote the following code:
if(subCategoryChildNode.hasChildNodes()){
// parse 'Subcategory' childs
NodeList productNL = subCategoryChildElmt.getElementsByTagName("product");
if(productNL.getLength() > 0){
ArrayList<Product> productAL = new ArrayList<Product>();
Product productBean = null;
for(int pCnt=0;pCnt<productNL.getLength();pCnt++){
Node productNode = productNL.item(pCnt);
Element productElmt = null;
// parse 'product' tag attributes
if(productNode.hasAttributes()){
productBean = new Product();
productElmt = (Element)productNode;
productBean.setmProductName(productElmt.getAttribute("name"));
}
if(productNode.hasChildNodes()){
NodeList productTypeNL = productElmt.getElementsByTagName("ProductType");
if(productTypeNL.getLength() > 0){
ArrayList<ProductType> ProductTypeAL = new ArrayList<ProductType>();
ProductType productTypeBean = null;
for(int ptCnt=0;ptCnt<productTypeNL.getLength();ptCnt++){
Node productTypeNode = productTypeNL.item(ptCnt);
Element productTypeElmt = null;
if(productTypeNode.hasChildNodes()){
productTypeBean = new ProductType();
productTypeElmt = (Element)productTypeNode;
productTypeBean.setmProductType(XMLfunctions.getValue(productTypeElmt,"producttype"));
System.out.println("Product Types are "+ " "+XMLfunctions.getValue(productTypeElmt,"producttype"));
ProductTypeAL.add(productTypeBean);
}
productBean.setmProductTypes(ProductTypeAL);
}
productAL.add(productBean);
}
}
subCategoryBean.setmProducts(productAL);
}
}
subCategoryAL.add(subCategoryBean);
}
Here am getting the value is nokia alone.but i need to display the value nokia,samsung...if i have to run the app means getting single value.but i need to get the list of all values..
What's wrong in my code .. please check and give me solution fot these ???
The reason you're getting only one <producttype> (Nokia) instead of the complete list because you're looping over the length of <ProductType> nodes thinking you're looping over the <producttype> ones.
So, you need another inner loop to cover all the child product type nodes like
for(int ptCnt=0; ptCnt < productTypeNL.getLength(); ptCnt++) {
Node productTypeNode = productTypeNL.item(ptCnt);
if(productTypeNode.hasChildNodes()){
NodeList childProductTypeNL = productTypeNode.getChildNodes();
System.out.print("Product Types are: ");
for (int cptCnt=0; cptCnt < childProductTypeNL.getLength(); cptCnt++) {
productTypeBean = new ProductType();
productTypeBean.setmProductType (
childProductTypeNL.item(cptCnt).getTextContent());
System.out.print(productTypeBean.getmProductType() + ", ");
ProductTypeAL.add(productTypeBean);
}
}
productBean.setmProductTypes(ProductTypeAL);
}
I've directly used the Node.getChildNodes() and Node.getTextContexnt() methods, instead of type casting to Element first and using its methods or the XMLfunctions utility class.
I also recommend using different names for child nodes instead of relying on using a different case to avoid such problems in future. A simple way to avoid name collision (when you're not able to come up with a different name) is to simply use a plural like <ProductTypes> for the parent tag.
However, a better approach when you need to parse deep within a DOM tree is to use an XPath to directly get the list of nodes you're interested in. I'm not entirely sure what the program does but just to give you an example an XPath like
String xpath = "//product[#name=\"viki\"]/ProductType/producttype";
would give you the NodeList for <producttype> nodes directly.
I'd say one of the problem of your code (might be others), is that you declare your productTypeBean and productTypeElmt before your for loop, and since it's not required after, it isn't needed.
if(subCategoryChildNode.hasChildNodes()){
// parse 'Subcategory' childs
NodeList productNL = subCategoryChildElmt.getElementsByTagName("product");
if(productNL.getLength() > 0){
ArrayList<Product> productAL = new ArrayList<Product>();
Product productBean = null;
for(int pCnt=0;pCnt<productNL.getLength();pCnt++){
Node productNode = productNL.item(pCnt);
Element productElmt = null;
// parse 'product' tag attributes
if(productNode.hasAttributes()){
productBean = new Product();
productElmt = (Element)productNode;
productBean.setmProductName(productElmt.getAttribute("name"));
}
if(productNode.hasChildNodes()){
NodeList productTypeNL = productElmt.getElementsByTagName("ProductType");
if(productTypeNL.getLength() > 0){
ArrayList<ProductType> ProductTypeAL = new ArrayList<ProductType>();
for(int ptCnt=0;ptCnt<productTypeNL.getLength();ptCnt++){
Node productTypeNode = productTypeNL.item(ptCnt);
if(productTypeNode.hasChildNodes()){
ProductType productTypeBean = new ProductType();
Element productTypeElmt = (Element)productTypeNode;
productTypeBean.setmProductType(XMLfunctions.getValue(productTypeElmt,"producttype"));
System.out.println("Product Types are "+ " "+XMLfunctions.getValue(productTypeElmt,"producttype"));
ProductTypeAL.add(productTypeBean);
}
productBean.setmProductTypes(ProductTypeAL);
}
productAL.add(productBean);
}
}
subCategoryBean.setmProducts(productAL);
}
}
subCategoryAL.add(subCategoryBean);
}

Parsing xml string containing hyperlink

I am using DOM to parse an XML string as in the following example. This works great except in one instance. The document which I am trying to parse looks like this:
<response requestID=\"1234\">
<expectedValue>Alarm</expectedValue>
<recommendations>For steps on how to resolve visit Website and use the search features for \"Alarm\"<recommendations>
<setting>Active</setting>
<response>
The code I used to parse the XML is as follows:
try {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlResult));
Document doc = db.parse(is);
NodeList nlResponse = doc.getElementsByTagName("response");
String[] String = new String[3]; //result entries
for (int i = 0; i < nlResponse.getLength(); i++) {
Element e = (Element) nlResponse.item(i);
int c1 = 0; //count for string array
NodeList ev = e.getElementsByTagName("expectedValue");
Element line = (Element) ev.item(0);
String[c1] = (getCharacterDataFromElement(line));
c1++;
NodeList rec = e.getElementsByTagName("recommendations");
line = (Element) rec.item(0);
String[c1] = (getCharacterDataFromElement(line));
c1++;
NodeList set = e.getElementsByTagName("settings");
line = (Element) set.item(0);
String[c1] = (getCharacterDataFromElement(line));
c1++;
I am able to parse the code and put the result into a string array (as opposed to the System.out.println()). With the current code, my string array looks as follows:
String[0] = "Alarm"
String[1] = "For steps on how to resolve visit"
String[2] = "Active"
I would like some way of being able to read the rest of the information within "Recommendations" in order to ultimately display the hyperlink (along with other output) in a TextView. How can I do this?
I apologize for my previous answer in assuming your xml was ill-formed.
I think what is happening is that your call to the getCharacterDataFromElement is only looking at the first child node for text, when it will need to look at all the child nodes and getting the href attribute as well as the text for the 2nd child node when looking at the recommendations node.
e.g. after getting the Element for recommendation
String srec = "";
NodeList nl = line.getChildNodes();
srec += nl.item(0).getTextContent();
Node n = nl.item(1);
NamedNodeMap nm = n.getAttributes();
srec += "" + n.getTextContent() + "";
srec += nl.item(2).getTextContent();
String[c1] = srec;

Categories