Solved

Followup Question: Trouble Using the RestTemplate to retrieve List of Objects

Posted on 2013-01-25
6
516 Views
Last Modified: 2013-02-03
Hello -

Got a couple followup questions regarding how to handle parsing different XML file formats.  What we have is a requirement to build in scalability via configurations placed in a properties file to be able to handle the following input XML file formats:

case 1:

<ITEMS>
  <ITEM>
    <columnName1>1</columnName1>
    <columnName2>2</columnName2>

case 2:

< ITEMS >
  <ITEM columnName1="1" columnName2="2"/>
</ITEMS >

case 3:

<ITEMS>
  <ITEM>
    <COLUMN NAME="columnName1" VALUE="1"/>
    <COLUMN NAME="columnName2" VALUE="2"/>  

Open in new window



We are loading an array of linkedhashmaps based on the properties file parm that holds the array of elements expected in the web service content xml seen below


#WebService Content Node Elements
rest.service.node.elements.xml=ID,objectType,uuid,version,contentTypesIDs,creationDate,description,displayName,modificationDate,name,typeID,userID

Open in new window


The problem we are running into is understanding what would be the better way of accessing data in the XML when dealing with each of these file formats? The thought right now is to either include a parm in the properties files or to pass as an arg at runtime to let us know which of the above 3 formats we are dealing with. Then via a case or if statements inside the loop that goes through the element names load the LinkedHashMap's to be loaded into the DB.

We have not had any trouble implementing parsing the input into and accessing the data from a DOM tree from xml formatted as Case 1 above…. just not sure how to go about handling these other XML formats? Any suggestions?

Thanks
0
Comment
Question by:West100
  • 3
  • 3
6 Comments
 
LVL 35

Expert Comment

by:mccarl
Comment Utility
No, you shouldn't need to tell the code what format to expect. I would say that they are different enough for the code to be able to work it out itself.

Case 1 and case 3 are quite similar. In your loop that iterates through all the 'childNodes' of your ITEM element, you would just put in a test to see if the childNodes 'name' is equal to 'COLUMN' then get the NAME and VALUE attributes are populate the Map with those, otherwise use the childNodes 'name' and it's textContent to populate the Map.

To handle case 2, I would just add an extra test, that if the number of childNodes of your ITEM element is ZERO, then iterate through all the ITEM element's attributes and use the name and value of each attribute to populate the Map.


If the above isn't totally clear, send me through your code (at least the DOM processing part that you have now, that handles case 1) and I will show you what I am talking about!
0
 

Author Comment

by:West100
Comment Utility
Here it goes …..The below method works for what I have for Case 1. I do understand and agree with what you are suggesting regarding the 3 cases…. that the code itself should be able to handle the varying XML format differences. My problem is that we do want this app to be configurable and that xPath seems to be a clean possibility. So you will notice that because we want to make this app as configurable as possible have decided to try to use Xpath to access data.  By including the correct root node in a properties file parm we should be able to tell the app what the structure of the xml is……. and/or at least where inside the XML the data is located.

public void loadHMapArray_XP(String URLContent, ApplicationContext appContext)throws XmlMappingException, IOException, Exception {

        String xmlCase1 = "<ns2:getSocialGroupsResponse xmlns:ns2=\"http://jsoftware.com/clearspace/webservices\"><return><ID>1009</ID><objectType>776</objectType><uuid></uuid><version>1</version><contentTypesIDs>1100</contentTypesIDs><contentTypesIDs>96891546</contentTypesIDs><contentTypesIDs>1</contentTypesIDs><contentTypesIDs>37</contentTypesIDs><contentTypesIDs>102</contentTypesIDs><contentTypesIDs>3227383</contentTypesIDs><contentTypesIDs>18</contentTypesIDs><creationDate>2012-07-05T19:48:36.061-06:00</creationDate><description>This a demo of what a Group can do</description><displayName>demo-group</displayName><modificationDate>2012-12-07T17:25:57.060-07:00</modificationDate><name>Demo Group</name><typeID>0</typeID><userID>2007</userID></return>" + 
                                                                    "<return><ID>1017</ID><objectType>700</objectType><uuid></uuid><version>1</version><contentTypesIDs>1100</contentTypesIDs><contentTypesIDs>96891546</contentTypesIDs><contentTypesIDs>1</contentTypesIDs><contentTypesIDs>37</contentTypesIDs><contentTypesIDs>102</contentTypesIDs><contentTypesIDs>3227383</contentTypesIDs><contentTypesIDs>18</contentTypesIDs><creationDate>2012-10-25T14:03:38.843-06:00</creationDate><description>testing private group</description><displayName>lisa-private-group</displayName><modificationDate>2012-11-15T11:35:19.782-07:00</modificationDate><name>lisa private group</name><typeID>2</typeID><userID>2007</userID></return></ns2:getSocialGroupsResponse>";
        String xmlCase2 = "<ns2:getSocialGroupsResponse xmlns:ns2=\"http://jsoftware.com/clearspace/webservices\"><return ID=\"1001\" objectType=\"700\" uuid=\"\" version=\"1\" contentTypesIDs=\"1100\" contentTypesIDs=\"96891546\" contentTypesIDs=\"1\" contentTypesIDs=\"37\" contentTypesIDs=\"102\" contentTypesIDs=\"3227383\" contentTypesIDs=\"18\" creationDate=\"2012-07-05T19:48:36.061-06:00\" description=\"This a demo of what a Group can do\" displayName=\"demo-group\" modificationDate=\"2012-12-07T17:25:57.060-07:00\" name=\"Demo Group\" typeID=\"0\" userID=\"2007\"/>" + 
                                                                    "<return ID=\"1017\" objectType=\"700\" uuid=\"\" version=\"1\" contentTypesIDs=\"1100\" contentTypesIDs=\"96891546\" contentTypesIDs=\"1\" contentTypesIDs=\"37\" contentTypesIDs=\"102\" contentTypesIDs=\"3227383\" contentTypesIDs=\"18\" creationDate=\"2012-10-25T14:03:38.843-06:00\" description=\"testing private group\" displayName=\"lisa-private-group\" modificationDate=\"2012-11-15T11:35:19.782-07:00\" name=\"lisa private group\" typeID=\"2\" userID=\"2007\"/></ns2:getSocialGroupsResponse>";
           String xmlCase3 = "<ns2:getSocialGroupsResponse xmlns:ns2=\"http://jsoftware.com/clearspace/webservices\"><return><COLUMN> NAME=\"ID\" VALUE=\"1001\"</COLUMN><COLUMN> NAME=\"objectType\" VALUE=\"700\" </COLUMN><COLUMN> NAME=\"uuid\" VALUE=\"\" </COLUMN><COLUMN> NAME=\"version\" VALUE=\"1\" </COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"1100\" </COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"96891546\" </COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"1\" </COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"37\" </COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"102\" </COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"3227383\" </COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"18\" </COLUMN><COLUMN> NAME=\"creationDate\" VALUE=\"2012-07-05T19:48:36.061-06:00\" </COLUMN><COLUMN> NAME=\"description\" VALUE=\"This a demo of what a Group can do\" </COLUMN><COLUMN> NAME=\"displayName\" VALUE=\"demo-group\" </COLUMN><COLUMN> NAME=\"modificationDate\" VALUE=\"2012-12-07T17:25:57.060-07:00\" </COLUMN><COLUMN> NAME=\"name\" VALUE=\"Demo Group\" </COLUMN><COLUMN> NAME=\"typeID\" VALUE=\"0\" </COLUMN><COLUMN> NAME=\"userID\" VALUE=\"2007\" </COLUMN></return>" + 
                                        "<return><COLUMN> NAME=\"ID\" VALUE=\"1017\"</COLUMN><COLUMN> NAME=\"objectType\" VALUE=\"700\"</COLUMN><COLUMN> NAME=\"uuid\" VALUE=\"\"</COLUMN><COLUMN> NAME=\"version\" VALUE=\"1\"</COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"1100\"</COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"96891546\"</COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"1\"</COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"37\"</COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"102\"</COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"3227383\"</COLUMN><COLUMN> NAME=\"contentTypesIDs\" VALUE=\"18\"</COLUMN><COLUMN> NAME=\"creationDate\" VALUE=\"2012-10-25T14:03:38.843-06:00\"</COLUMN><COLUMN> NAME=\"description\" VALUE=\"testing private group\"</COLUMN><COLUMN> NAME=\"displayName\" VALUE=\"lisa-private-group\"</COLUMN><COLUMN> NAME=\"modificationDate\" VALUE=\"2012-11-15T11:35:19.782-07:00\"</COLUMN><COLUMN> NAME=\"name\" VALUE=\"lisa private group\"</COLUMN><COLUMN> NAME=\"typeID\" VALUE=\"2\"</COLUMN><COLUMN> NAME=\"userID\" VALUE=\"2007\"</COLUMN></return>" + "</ns2:getSocialGroupsResponse>";
 

public void loadHMapArrayList_xp(String URLContent, ApplicationContext appContext)throws XmlMappingException, IOException, Exception {

    	List <LinkedHashMap> hashList =  new ArrayList<LinkedHashMap>();
    	List <HashMap> hList =  new ArrayList<HashMap>();        
	List<String> elements = ENURestConfiguration.getInstance().getElementList();
        
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = builder.parse(new InputSource(new StringReader(xmlCase1)));
        Node rootNode = doc.getDocumentElement();
        System.out.println("\nrootNode.getNodeName() of the Document doc is =>" + rootNode.getNodeName() + "<=");
        System.out.println("rootNode.getChildNodes().getLength() = " +rootNode.getChildNodes().getLength());
        
        XPathFactory xpf = XPathFactory.newInstance();
        XPath xp = xpf.newXPath();

	//XPathExpression expr = xp.compile("//return/COLUMN"); <--For testing xmlCase3
        //XPathExpression expr = xp.compile("//return");<--For testing xmlCase1

        NodeList nodes = (NodeList)xp.evaluate("//return", doc, XPathConstants.NODESET); //<--For testing xmlCase1
        //NodeList nodes = (NodeList)xp.evaluate("//return/COLUMN", doc, XPathConstants.NODESET); //<--For testing xmlCase3
        System.out.println("nodes.getLength() = " +nodes.getLength());
        
        //Loop thru Nodes found in XML(Node defined as <return> ..... to </return>
        for (int i = 0; i < rootNode.getChildNodes().getLength(); i += 1) {    
            Node item = nodes.item(i);
            System.out.println("nodes item = " +item.getNodeName() + " : " + item.getTextContent() + " : " + item.getNodeValue());
           
            LinkedHashMap mMap = new LinkedHashMap();
            
            //Loop thru Nodes/Elements ArrayList created from Properties file element List
            //Load HashMap with XML elements/data
            for (int x=0; x < elements.size(); x++) {

		//Set Xpath expression to access data
                String elementName = elements.get(x).toString();
                nodeValueXpath = "./" + elementName;
                System.out.println("nodeValueXpath  = " + nodeValueXpath);
		
		//This if statement should only be triggered if the following was set as the xPath root "//return/COLUMN"
                if (item.getNodeName().equals("COLUMN")){
		    //The following is not pulling data?? for xmlCase3 when tested…
		    //nodeValueXpath may not be set correct here ???
                    String str = XPathAPI.eval(rootNode.getChildNodes().item(i), nodeValueXpath).toString();    
                    System.out.println("=>" + str + "<=\n"); 
                    //mMap.put(elementName,str);
                }else{
    
                //XPATH EXPRESSION from nodeValueXpath ....  "./"+elementName; works here for xmlCase1
                String str = XPathAPI.eval(rootNode.getChildNodes().item(i), nodeValueXpath).toString();    
                System.out.println("=>" + str + "<=\n");  
                mMap.put(elementName,str);
                //mMap.put(elements.get(x).toString(), ((Element) rootNode.getChildNodes().item(i)).getElementsByTagName(elements.get(x).toString()).item(0).getTextContent());
            }  
            
          
            //Cast LinkedHashMap to a HashMap for type handleable by spring
            HashMap hm = (HashMap)mMap;
        
            hList.add(hm);
            
        }
        
        System.out.println("loadHMapArrayList::hashList size = " + hList.size());
        
    }

Open in new window


Not sure if I'm just making my life more difficult but initially it appeared that the XML structure of Case 3 seemed to be failing as invalid so I changed the following from:

<ITEMS>
  <ITEM>
    <COLUMN NAME="columnName1" VALUE="1"/>
    <COLUMN NAME="columnName2" VALUE="2"/>  
to

<ITEMS>
  <ITEM>
    <COLUMN> NAME="columnName1" VALUE="1"</COLUMN>
    <COLUMN> NAME="columnName2" VALUE="2"</COLUMN>  


So the above code/method works for Case 1 XML.  For Case 3 the above works up to the COLUMN if statement with the revamped Case 3 XML…. I just have not been able to determine how to pull the values out of those COLUMN tags then populate the hash map?  I have not gotten to Case 2 yet so  not completely sure what I'm going to need for that one yet?

Thanks for the help.
0
 
LVL 35

Accepted Solution

by:
mccarl earned 500 total points
Comment Utility
Ok, a few things came up while testing the above and what I was thinking..

First and foremost, try not to fall into the trap of attempting to make your code TOO configurable. I know it is easy to do, I do it myself sometimes. The problem comes when you end up putting in 20 hours coding effort to make something "fully configurable" and there is only a 10% chance of ever being used for side case X and would have only taken 1 hour to actually implement logic to handle X. I agree that it is good to have some amount of flexibility but a line has to be drawn at some point. Otherwise your properties file is going to end up being "code" anyway and something that someone else would need to spend considerable time to understand before they could change anything anyway.

That being said, as a learning experience for you, I still went and looked at what I was thinking for the above, however there are still issues...
For case 3, the XML that you have changed it to would be VERY UNLIKELY to ever be a case that you would encounter. To go to the length of having the response in an XML format, and then having the column names and values as just text content of an element... I would shoot anyway that did anything like that. It would be IMPOSSIBLE to have the code cater for lots of different cases if this were a possibility. I have changed it back to your original XML format for case 3
For case 2, that XML is actually invalid and will never be parsed by any XML parser. You can't have multiple attributes of an element with the same name, 'contentTypeIDs'. Which brings up a question... how would this be represented in the XML to be valid? It made me realise that these 3 different cases aren't examples that you have actually experienced, are they? Are they just case that you are assuming that may happen and are therefore trying to cater for? Again, see my first paragraph on trying to make things TOO flexible. So what did I do to make this case valid XML? I concatenated the contentTypeIDs into one attribute. Is this right? Well since (I am assuming) this is just a synthetic case, there is no right answer.
Along the lines of the above, what was your code doing with these multiple contentTypeIDs elements? I believe that your code was missing all but the last encountered one as well. This is how any Map works, that if you "put()" a number of times to the same "key", each time the previous value gets lost and so only the last "put()" value is retained. This is a pretty complex thing to decide how to handle, and is up to you, as only you know how you would want to see this represented in your database. In the code below, I have just added a small method to make any new values "append" to previous values rather than replace them, but that is just one possibility.
Just a minor, general thing about Java... I noticed that you were having issues with LinkedHashMap vs HashMap etc. Have a look at the code below for an example, but in general you should program against the Interface rather than the class (where possible). If you have a look at my List's and Map's usages, the ArrayList and LinkedHashMap are only actually used when I instantiate them (ie. the "new" operator). All other variable declarations, usages are via the Interface type and this makes things much cleaner. Also note that now, if you want to change from say a ArrayList implemetation to a LinkedList implementation, you only have to change in ONE spot. Now I know that this is not always possible. Sometimes that Interface doesn't contain a method that you need to call that is on the actual class, and so you need to define your variable to be the actual class. But you should at least TRY to just use the interface in the first sense and only then if you need the extra functionality, use the class.

Ok, so anyway, as I said the below is more just for learning. I personally probably wouldn't try to make it even this flexible (especially if it is only for cases the MAY happen in the future and not something that you can fully test with now). One other thing to note with the below, is that instead of passing the list of elements (from your properties file) into this code, it just gets ALL content. In the way that I showed how to make the DB code configurable, that will just pick out the Map values that it is configured to get anyway, so there is no point doing this filtering twice. Also, this aligns with how your JSON processing will work, where IT will give you a Map with ALL the content from the original string too. Just leave it up to your DB code/configuration to "pick" out the bits that it is interested in saving to the DB.

Any other questions with the below, just let me know!

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class TestMultipleXMLFormats {
    
    public static void main(String[] args) throws IOException, Exception {
        String xmlCase1 = "<ns2:getSocialGroupsResponse xmlns:ns2=\"http://jsoftware.com/clearspace/webservices\"><return><ID>1009</ID><objectType>776</objectType><uuid></uuid><version>1</version><contentTypesIDs>1100</contentTypesIDs><contentTypesIDs>96891546</contentTypesIDs><contentTypesIDs>1</contentTypesIDs><contentTypesIDs>37</contentTypesIDs><contentTypesIDs>102</contentTypesIDs><contentTypesIDs>3227383</contentTypesIDs><contentTypesIDs>18</contentTypesIDs><creationDate>2012-07-05T19:48:36.061-06:00</creationDate><description>This a demo of what a Group can do</description><displayName>demo-group</displayName><modificationDate>2012-12-07T17:25:57.060-07:00</modificationDate><name>Demo Group</name><typeID>0</typeID><userID>2007</userID></return>" + "<return><ID>1017</ID><objectType>700</objectType><uuid></uuid><version>1</version><contentTypesIDs>1100</contentTypesIDs><contentTypesIDs>96891546</contentTypesIDs><contentTypesIDs>1</contentTypesIDs><contentTypesIDs>37</contentTypesIDs><contentTypesIDs>102</contentTypesIDs><contentTypesIDs>3227383</contentTypesIDs><contentTypesIDs>18</contentTypesIDs><creationDate>2012-10-25T14:03:38.843-06:00</creationDate><description>testing private group</description><displayName>lisa-private-group</displayName><modificationDate>2012-11-15T11:35:19.782-07:00</modificationDate><name>lisa private group</name><typeID>2</typeID><userID>2007</userID></return></ns2:getSocialGroupsResponse>";
        String xmlCase2 = "<ns2:getSocialGroupsResponse xmlns:ns2=\"http://jsoftware.com/clearspace/webservices\"><return ID=\"1001\" objectType=\"700\" uuid=\"\" version=\"1\" contentTypesIDs=\"1100,96891546,1,37,102,3227383,18\" creationDate=\"2012-07-05T19:48:36.061-06:00\" description=\"This a demo of what a Group can do\" displayName=\"demo-group\" modificationDate=\"2012-12-07T17:25:57.060-07:00\" name=\"Demo Group\" typeID=\"0\" userID=\"2007\"/>" + "<return ID=\"1017\" objectType=\"700\" uuid=\"\" version=\"1\" contentTypesIDs=\"1100,96891546,1,37,102,3227383,18\" creationDate=\"2012-10-25T14:03:38.843-06:00\" description=\"testing private group\" displayName=\"lisa-private-group\" modificationDate=\"2012-11-15T11:35:19.782-07:00\" name=\"lisa private group\" typeID=\"2\" userID=\"2007\"/></ns2:getSocialGroupsResponse>";
        String xmlCase3 = "<ns2:getSocialGroupsResponse xmlns:ns2=\"http://jsoftware.com/clearspace/webservices\"><return><COLUMN NAME=\"ID\" VALUE=\"1001\" /><COLUMN NAME=\"objectType\" VALUE=\"700\"  /><COLUMN NAME=\"uuid\" VALUE=\"\"  /><COLUMN NAME=\"version\" VALUE=\"1\"  /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"1100\"  /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"96891546\"  /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"1\"  /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"37\"  /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"102\"  /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"3227383\"  /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"18\"  /><COLUMN NAME=\"creationDate\" VALUE=\"2012-07-05T19:48:36.061-06:00\"  /><COLUMN NAME=\"description\" VALUE=\"This a demo of what a Group can do\"  /><COLUMN NAME=\"displayName\" VALUE=\"demo-group\"  /><COLUMN NAME=\"modificationDate\" VALUE=\"2012-12-07T17:25:57.060-07:00\"  /><COLUMN NAME=\"name\" VALUE=\"Demo Group\"  /><COLUMN NAME=\"typeID\" VALUE=\"0\"  /><COLUMN NAME=\"userID\" VALUE=\"2007\"  /></return>" + "<return><COLUMN NAME=\"ID\" VALUE=\"1017\" /><COLUMN NAME=\"objectType\" VALUE=\"700\" /><COLUMN NAME=\"uuid\" VALUE=\"\" /><COLUMN NAME=\"version\" VALUE=\"1\" /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"1100\" /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"96891546\" /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"1\" /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"37\" /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"102\" /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"3227383\" /><COLUMN NAME=\"contentTypesIDs\" VALUE=\"18\" /><COLUMN NAME=\"creationDate\" VALUE=\"2012-10-25T14:03:38.843-06:00\" /><COLUMN NAME=\"description\" VALUE=\"testing private group\" /><COLUMN NAME=\"displayName\" VALUE=\"lisa-private-group\" /><COLUMN NAME=\"modificationDate\" VALUE=\"2012-11-15T11:35:19.782-07:00\" /><COLUMN NAME=\"name\" VALUE=\"lisa private group\" /><COLUMN NAME=\"typeID\" VALUE=\"2\" /><COLUMN NAME=\"userID\" VALUE=\"2007\" /></return></ns2:getSocialGroupsResponse>";
        
        String itemXPathParameter = "//return";
        String columnElementNameParameter = "COLUMN";
        String nameAttributeNameParameter = "NAME";
        String valueAttributeNameParameter = "VALUE";
        
        
        
        TestMultipleXMLFormats test = new TestMultipleXMLFormats();
        
        List<Map<String, String>> mapList;
        
        mapList = test.loadHMapArray_XP(xmlCase1, itemXPathParameter, columnElementNameParameter, nameAttributeNameParameter, valueAttributeNameParameter);
        System.out.println("CASE 1:\nList size = " + mapList.size() + "\n" + mapList + "\n\n");
        
        mapList = test.loadHMapArray_XP(xmlCase2, itemXPathParameter, columnElementNameParameter, nameAttributeNameParameter, valueAttributeNameParameter);
        System.out.println("CASE 2:\nList size = " + mapList.size() + "\n" + mapList + "\n\n");
        
        mapList = test.loadHMapArray_XP(xmlCase3, itemXPathParameter, columnElementNameParameter, nameAttributeNameParameter, valueAttributeNameParameter);
        System.out.println("CASE 3:\nList size = " + mapList.size() + "\n" + mapList + "\n\n");
    }
    
    public List<Map<String, String>> loadHMapArray_XP(String content, String itemXPath, String columnElementName, String nameAttributeNameParameter, String valueAttributeNameParameter) throws IOException, Exception {
        
        List<Map<String, String>> hList = new ArrayList<Map<String, String>>();
        
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = builder.parse(new InputSource(new StringReader(content)));
        
        XPathFactory xpf = XPathFactory.newInstance();
        XPath xp = xpf.newXPath();
        
        NodeList nodes = (NodeList) xp.evaluate(itemXPath, doc, XPathConstants.NODESET);
        
        for (int i = 0; i < nodes.getLength(); i += 1) {
            Node item = nodes.item(i);
            
            Map<String, String> mMap = new LinkedHashMap<String, String>();
            
            NodeList childNodes = item.getChildNodes();
            if (childNodes.getLength() == 0) {
                // No child elements so this must be case 2
                NamedNodeMap attributes = item.getAttributes();
                
                for (int j = 0; j < attributes.getLength(); j++) {
                    Node attribute = attributes.item(j);
                    putOrAppendToMap(mMap, attribute.getNodeName(), attribute.getNodeValue());
                }
            } else {
                for (int j = 0; j < childNodes.getLength(); j++) {
                    Node childNode = childNodes.item(j);
                    String elementName = childNode.getNodeName();
                    
                    if (elementName.equals(columnElementName)) {
                        // The element name == "COLUMN" or whatever the parameter is set to, so this must be case 3
                        putOrAppendToMap(mMap, childNode.getAttributes().getNamedItem(nameAttributeNameParameter).getNodeValue(), childNode.getAttributes().getNamedItem(valueAttributeNameParameter).getNodeValue());
                    } else {
                        // Must be case 1
                        putOrAppendToMap(mMap, elementName, childNode.getTextContent());
                    }
                }
            }
            
            hList.add(mMap);
            
        }
        
        return hList;
    }
    
    private void putOrAppendToMap(Map<String, String> map, String key, String value) {
        String previousValue = map.get(key);
        
        if (previousValue != null) {
            value = previousValue + "," + value;
        }
        
        map.put(key, value);
    }
}

Open in new window

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:West100
Comment Utility
Hello -

Yes I do agree with your perspective on going to far to soon with making an app  configurable. Until we have more specifics I do feel we have reached that point of diminished returns....  do appreciate your opinion and help along the way.  

These 3 cases were supplied to us from tech/business consultants currently on the project presented as possibilities. Because an overall lack of experience with XML and what we should expect from the provider these cases/xml mockup examples is what we have had to work with. You are completely correct in that we are assuming that these are cases/scenarios that may happen and are trying to cater for them in advance.   If we have multiple contentTypeIDs we are going to have to attempt to concatenate into one attribute as you suggest and show. Dealing with multiple contentTypeIDs was not something that I had gotten to yet.

Your example ran perfectly, got right into what we are dealing with and provided us with some ideas to consider..

I'm sure we will have more questions … Thanks again.
0
 

Author Closing Comment

by:West100
Comment Utility
Sorry forgot to accept as solution earlier ..... Thanks again
0
 
LVL 35

Expert Comment

by:mccarl
Comment Utility
Not a problem! Hope it helps you get to your solution! :)
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Read about why website design really matters in today's demanding market.
I've been asked to discuss some of the UX activities that I'm using with my team. Here I will share some details about how we approach UX projects.
This tutorial demonstrates how to identify and create boundary or building outlines in Google Maps. In this example, I outline the boundaries of an enclosed skatepark within a community park.  Login to your Google Account, then  Google for "Google M…
Any person in technology especially those working for big companies should at least know about the basics of web accessibility. Believe it or not there are even laws in place that require businesses to provide such means for the disabled and aging p…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now