Getting XML elements as Key Value Map java

Get XML values as key value pair in Java

This simple java class would help to get values of the xml format as key and value map in java.

It has some limitation on the xml that you would be using, yet it would be a ground step for building other.

package helpers;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 *
 * Simple XML Class -
 * This XML Class is a simple helper only for specific case. Originally developed to get
 * key and value of flat xml.
 * Feel free to use this piece of code as you like with/out permission - if possible mention this site.
 * I am not responsible for any consequences that would result after using this piece of code.
 *
 * @author http://gullele.com
 */
public class XMLHelper {
	private DocumentBuilderFactory documentBuilderFactory;
	private DocumentBuilder documentBuilder;

	public XMLHelper(){
		try{
			this.documentBuilderFactory = DocumentBuilderFactory.newInstance();
			this.documentBuilder = this.documentBuilderFactory.newDocumentBuilder();
		}
		catch(ParserConfigurationException pce){
			//log error
		}
	}

	//Simple test
	public static void main(String argv[]) {
		XMLHelper xmlHelper = new XMLHelper();
		  try {
			  String xmlDoc = "<?xml version="1.0"?><flatFields><java>6.0</java><xml>yes</xml><tags>given tags</tags><doc /><multipleRow /></flatFields>";
			  Document doc = xmlHelper.getDocumentBuilder().parse(
					  xmlHelper.getInputStream(xmlDoc)
			  );
			  doc.getDocumentElement().normalize();
			  NodeList nodeLst = doc.getDocumentElement().getChildNodes();
			  Map elemen = xmlHelper.getElementKeyValue(nodeLst);
			  Iterator it = elemen.entrySet().iterator();
			  while (it.hasNext()) {
				  Map.Entry pairs = (Map.Entry)it.next();
				  	System.out.println(pairs.getKey() + " = " + pairs.getValue());
			  }
			} catch (SAXParseException e) {
			   //log error
			} catch (SAXException e) {
				   //log error
			} catch (IOException e) {
				   //log error
			}
	}

	/**
	 * Provides NodeList from the given Document object by the tagName
	 * @param Document - doc
	 * @param tagname
	 * @return NodeList
	 */
	public NodeList getNodeListByTag(Document doc, String tagname){
		NodeList nodeList = null;
		if (doc !=null && !tagname.isEmpty()){
			nodeList = doc.getElementsByTagName(tagname);
		}
		return nodeList;
	}

	/**
	 *
	 * @param nodeList
	 * @return Map
	 */
	public Map getElementKeyValue(NodeList nodeList){
		Map elements = new HashMap();
		if (nodeList!=null && nodeList.getLength()>0 ){
			for(int i=0 ; i < nodeList.getLength() ; i++){
				Node node = nodeList.item(i); //Take the node from the list
				NodeList valueNode = node.getChildNodes(); // get the children of the node
		        String value = (valueNode.item(0)!=null) ? valueNode.item(0).getNodeValue() : "";
		        elements.put(node.getNodeName(), value);
			}
		}
		return elements;
	}

	/**
	 * Returns InputString given string
	 * @param string
	 * @return InputStream
	 */
	public InputStream getInputStream(String string){
		InputStream inputStream = null;
		if (!string.isEmpty()){
			try{
				inputStream = new ByteArrayInputStream(string.getBytes("UTF-8"));
			}
			catch(UnsupportedEncodingException uee){
			}
		}
		return inputStream;
	}

	/**
	 * Setters and getters
	 * @return
	 */
	public DocumentBuilderFactory getDocumentBuilderFactory() {
		return documentBuilderFactory;
	}
	public void setDocumentBuilderFactory(
			DocumentBuilderFactory documentBuilderFactory) {
		this.documentBuilderFactory = documentBuilderFactory;
	}
	public DocumentBuilder getDocumentBuilder() {
		return documentBuilder;
	}
	public void setDocumentBuilder(DocumentBuilder documentBuilder) {
		this.documentBuilder = documentBuilder;
	}
}

An output for the test main method would be:
tags = given tags
doc =
multipleRow =
xml = yes
java = 6.0

Also Recommended for You

See how to handle unicode in database with java here

Find the longest palindrome sequence from given characters

Can you find pairs that makes K complementary from the array?

Convering String to inputStream java

There are a number of places where string would be needed to be changed to InputStream object. For example the Dom parser would expect an InputStream for the creation of its DocumentBuilder

Here is the simple yet powerful single line doing the task!!

inputStream = new ByteArrayInputStream(string.getBytes("UTF-8"));

Could not open Hibernate Session for transaction

This problem happens when the connection to the database is disconnected or was not created at all by the application, but pool assumes connection is established.
Remedy for this could be checking credential to the database [username, password, host, port] and also checking the connection object before proceeding to database tasks like reading or updating.

hibernate automatically saves/edits objects that are updated

Kind of mysterious – all you want to do would be to update the some component on your java logic and it is automatically saved in the database.
Here is the typical scenario, if you are updating collection of objects and and updating one object would also update others based on some logic – say reordering of numbers, the session would all be saved without saving all the collections – yup I got this exact situation and the reason was

After the update, I have another ajax call to the backend where I would get the list of objects. And the method which collect the objects was annotated as Transactional. In this case, all the dirty objects in the session would be saved though what I wanted was to read only.

So, I changed the annotation to Transactional(readOnly=true) – that took care of it.

Showing error message on selectOneMenu while selecting default

So, we have a menu, brimmed with our objects from list/database. The intention would be creating a default “Select” kind of the first row and to brag on the user when s/he selects the default.

The trick is simple, create the first list with null object and label it as Select. Lets show it with simple example.
We want to have a list of programming languages on our select menu. And, the first would be a default object.

    //Actual domain class
    class Language{
        private String name;
        private String type;
        private boolan isCompiled;

       getters/setters goes here
   }
   //Bean class
   class someBean{
        private List languages;
        .
        .
        public String getLanguages(){
            //Let languages would be filled by some service or factory
            this.languages = someLanguageFactory.getAllLanguages(); 
           //Assign the first element as null
           this.languages.add(0, null);
       }
   }
   
   //JSF page
   :
   :
   <h:selectOneMenu id="selectLanguage" value="someBean.languages" 
     requred="true" ....

This should do the task, make the list required, and populate the first list null. So, during validation if the selection is null it would be rejected as we have told it to watch an eye on blank fields.

datatable/component not updated after deleting and adding new one

During working on tabular data, it is common to have edit and delete command buttons for each row.

And, after we update or delete we want the table to be updated. Let’s looks some simple example.

The table on the JSF might look like


<form id="tablularForm">
<h:datatable id="tabularData" value="#{someBean.list}"
binding="#{someBean.htmlDataTable}" var="data">
<h:column>
<h:outputText id="colum1" value="#{data.column}" />
</h:column>
<h:column>
<h:CommandLink id="edit" value="Edit" action="#{someBean.editAction}" reRender="tabularData"/>
</h:column>
<h:column>
<h:CommandLink id="delete" value="Delete" action="#{someBean.deleteAction}" reRender="tabularData"/>
</h:column>
</h:datatable>
<h:CommandButton id="add" value="add" action="#{someBean.addAction}" />
</h:form>

The above ideal table would work fine.

The datatable would store values by reading from bean and would be updated on Edit and Delete actions accordingly.

This is b/c of the reRender attribute of the components.

The glitch comes when there is no any data in the table. Say you daleted all the data and you want to add a new one.

Or it is the brand new table to be added.

The row would be added but it wont be shown on the table. In short the table would not be updated.

The thing is when we use reRender, we have to use the enclosing component not the component to be safe!.

When it tries to rerender if the component was not there initially, it wont rerender it.
So, here we can use the id of the form for rerendering the datatable and we would be OK.

See why jsf apps are slow in cases

test

Wanted but not invoked: However, there were other interactions with this mock: ->

Wanted but not Invoked Error in mockito and its solution

This happens with mockito when trying to verify the invocation on an object with specific method.

But what happens is you have interacted with other method of that object but not the one mentioned.

If you have an object named CustomerService and say it has two methods named saveCustomer() and verifyExistingCustomer()

And mockito looks something like

verify(customerService, atleast(1)).verifyExistingCustomer(customer), 

But in your actual service you called the saveCustomer() at least once.. BINGO you would get that error.

Also Recommended for you

See how you can get started with mockito with simple example

Do you like Algorithms?

Find K complementary numbers from given array

Can you form the longest palindrome from the given random characters?

eraser

deleted object would be re-saved by cascade (remove deleted object from associations):

Kind of oxymoron ha?!.

You try to delete but you are told it would be re-saved.

Actually it is a safe guard by hibernate that this action is meaningless unless you do the actual stuff.

Two things to check:

  • make sure any collection that holds the object is cleared before deleting the object
  • Clear the child object from the parent object before deleting the child if you have cascade="all"

See also Why jsf applications get slow when using a jpa connection

Learn How to add unicode characters to database from hibernate application

Action in bean is never triggered/called from jsf page

One plus side of the compiled languages would be telling us every error during/after compilation which would save a lot time from chicanery. But, in JSF you may get unexpected error which is a silent.

The page would run and the action linked to, say command button or command link, may not be triggered.

If you got that, just check your form fields – especially if you are working with datatable, make sure all the conversion and validations are working as expected. If the validation/conversion is not working properly, then the framework would exit before reaching the backend.

One way to troubleshoot this would be to have <h:messages /> with appropriate attributes, like adding showDetail=”false” showSummary=”true”, on your form – that, definitely, would help you to debug the problem.