?
Solved

Reading all CDATA in an XML String into a Java ArrayList?

Posted on 2011-10-14
11
Medium Priority
?
725 Views
Last Modified: 2012-05-12
I'd like to read all CDATA associated to a child node and store them into a java ArrayList! If you could suggest a simple and quick way I'd grately appreciate it!

Thanks!

In would like to have a little routine testing the txnid for an specific value and read all the associated CDATA queries in different Array Elements.

<?xml version="1.0" encoding="utf-8" standalone="yes" >   
<ZQueries txid="Group 1" version="1.0.0.0">  
<ZQuery name="Some Name 1" savename="SomeFileName1.xml">   
<![CDATA[SELECT ...........    ]]>   
</ZQuery>  
<ZQuery name="Some Name 2" savename="SomeFileName.xml">  
<![CDATA[SELECT .............     ]]>  
</ZQuery> 
<ZQuery name="some name 3" savename="someFileName.xml"> 
<![CDATA[SELECT ..............   ]]>   
</ZQuery>  
</ZQueries>  
<ZQueries txid="Group 2" version="1.0.0.0">  
<ZQuery name="Some Name 1" savename="SomeFileName1.xml">   
<![CDATA[SELECT ...........    ]]>   </ZQuery>  
<ZQuery name="Some Name 2" savename="SomeFileName.xml">  
<![CDATA[SELECT .............     ]]>    
</ZQueries>

Open in new window

0
Comment
Question by:snajalm
  • 7
  • 4
11 Comments
 
LVL 47

Expert Comment

by:for_yan
ID: 36971869
Sorry I only manged to read your file this way
(and still I had to close beforehand manually one ZQuery at the verty bottom where
</Zquery> is missing  )
exact input file - pasted form your question but with closing </ZQuery> added
is attached

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.ParserAdapter;

import java.io.*;
import java.util.ArrayList;

public class ReadXMLFile {
   static   ArrayList<String> data;
   public static void main(String argv[]) {

                  data = new ArrayList<String>();
    try {

	SAXParserFactory factory = SAXParserFactory.newInstance();
     	SAXParser saxParser = factory.newSAXParser();

	DefaultHandler handler = new DefaultHandler() {

	boolean bfname = false;
	boolean blname = false;
	boolean bnname = false;
	boolean bsalary = false;

	public synchronized void startElement(String uri, String localName,String qName,
                Attributes attributes) throws SAXException {

		if (qName.equalsIgnoreCase("ZQuery")) {
			bfname = true;
		}

	}

	public synchronized void endElement(String uri, String localName,
		String qName) throws SAXException {

		//System.out.println("End Element :" + qName);
        

	}

	public synchronized void characters(char ch[], int start, int length) throws SAXException {

		if (bfname) {
            String s =  new String(ch, start, length);
            ReadXMLFile.data.add(s);
			bfname = false;
		}


	}

     };
         ParserAdapter pa =
 new ParserAdapter(saxParser.getParser());
        pa.setContentHandler(handler);

        PrintStream psout = new PrintStream(new FileOutputStream("products_out.xml"));
     BufferedReader in = new BufferedReader(new FileReader("products.xml"));
    String str;
            psout.println("<Root>");
    while ((str = in.readLine()) != null) {
        if(str.startsWith("<?xml "))continue;
        if(str.startsWith("<ZQuery"))psout.print(str.trim());
        else psout.println(str.trim());
        
    }
        psout.println("</Root>");
    in.close();
        psout.close();


FileInputStream bais = new FileInputStream("products_out.xml");
  pa.parse(new InputSource(bais));
        for(String s : ReadXMLFile.data){
            System.out.println(s);
        }

        

     } catch (Exception e) {
       e.printStackTrace();
     }

   }

}

Open in new window


Output:
SELECT ...........    
SELECT .............     
SELECT ..............   
SELECT ...........    
SELECT ............. 

Open in new window



products.xml
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36971875
It does not want to read the first line (probably there is some solution to that)
then it requires to have one root element, and waht was most difficult for me
to find out is that there should not be carriage return or spaces between this piece
<ZQuery name="Some Name 2" savename="SomeFileName.xml">  
and this piece:
<![CDATA[SELECT .............     ]]>

Again, perhaps there isi an easy way to overcome it, but I re-wrote the file
making these changes and then parsed it
0
 

Author Comment

by:snajalm
ID: 36972271
Just before you send this solution, I came up with another solution which utlizes JDOM objects.  However I'm getting an exception which I'm not sure why is happening.  First of all what do you think about this solution which is a little compressed and how do you think I can get around the exception I'm getting?!

In this code I try to check the child nodes for a matching "txid" attribute and store the CDATA under it into an ArrayList.  This code is initially suggested by "FloppyDisk" on stackoverflow.com and I a just applied some modfications to it to fit my overall code!  
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
.
.
.
.

SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);  //build a JDOM doc from an input stream
ArrayList<String> queries = new ArrayList<String>();
Element root = doc.getRootElement();
            
Iterator elemIter = root.getDescendants();
                 
while (elemIter.hasNext()) {
     Element tempElem = (Element) elemIter.next();
     if (root.getChild("ZQueries").getAttributeValue("txid").equals(tempTxid)) {
             String CDATA = tempElem.getChildText("ZQueries");
             queries.add(CDATA);
      } 
}



Exception in thread "AWT-EventQueue-0" java.security.PrivilegedActionException:java.security.PrivilegedActionException: org.jdom.input.JDOMParseException: Error on line 1: Premature end of file.

Open in new window

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 47

Expert Comment

by:for_yan
ID: 36972284
Which file you were reading?
Please, post the exact input file.
As I mention the one you p[osted above didn't have
one of the closing tags and had a few more subtle problems
0
 

Author Comment

by:snajalm
ID: 36972302
I have renamed some of the fields for security reasons but the attached is the exact code I'm getting! myFile.xml
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36972359
No I can't execute getting error when I run weven before

 Element tempElem = (Element) elemIter.next();


java.lang.ClassCastException: org.jdom.Text cannot be cast to org.jdom.Element

I downloaded some Jdom.jar - maybe it is different version

With my code with slight modification I can read  MyFile.xml

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.ParserAdapter;

import java.io.*;
import java.util.ArrayList;

public class ReadXMLFile {
   static   ArrayList<String> data;
   public static void main(String argv[]) {

                  data = new ArrayList<String>();
    try {

	SAXParserFactory factory = SAXParserFactory.newInstance();
       // factory.setValidating(true);
	SAXParser saxParser = factory.newSAXParser();

	DefaultHandler handler = new DefaultHandler() {

	boolean bfname = false;
	boolean blname = false;
	boolean bnname = false;
	boolean bsalary = false;

	public synchronized void startElement(String uri, String localName,String qName,
                Attributes attributes) throws SAXException {

		//System.out.println("Start Element :" + qName);

		if (qName.equalsIgnoreCase("ZQuery")) {
			bfname = true;
		}

		if (qName.equalsIgnoreCase("ZQueries")) {
			blname = true;
                      int len = attributes.getLength();
            for(int j=0; j<len; j++){
               // System.out.println(attributes.getLocalName(j));
                if(attributes.getLocalName(j).equals("txnid"))
                System.out.println(attributes.getValue(j));
            }

		}
          /*
		if (qName.equalsIgnoreCase("NICKNAME")) {
			bnname = true;
		}

		if (qName.equalsIgnoreCase("SALARY")) {
			bsalary = true;
		}
        */

	}

	public synchronized void endElement(String uri, String localName,
		String qName) throws SAXException {

		//System.out.println("End Element :" + qName);
        

	}

	public synchronized void characters(char ch[], int start, int length) throws SAXException {
       // System.out.println(bfname + ": " +  new String(ch));

		if (bfname) {
            String s =  new String(ch, start, length);
			//System.out.println("First Name : " + new String(ch, start, length));
            ReadXMLFile.data.add(s);
			bfname = false;
		}


		if (blname) {
			//System.out.println("Last Name : " + new String(ch, start, length));
			blname = false;
		}
          /*
		if (bnname) {
		//	System.out.println("Nick Name : " + new String(ch, start, length));
			bnname = false;
		}

		if (bsalary) {
		//	System.out.println("Salary : " + new String(ch, start, length));
			bsalary = false;
		}
        */

	}

     };
         ParserAdapter pa =
 new ParserAdapter(saxParser.getParser());
        pa.setContentHandler(handler);
      // pa.parse("products.xml", handler);
    //    byte bytearray[] = "<ZQuery><![CDATA['This is the cdata']]></ZQuery>".getBytes();
            /*
        String outputFile = "changed.xml";
         DocumentBuilder domparser =
      DocumentBuilderFactory.newInstance().newDocumentBuilder();
         Document document = domparser.parse( new InputSource(new FileInputStream("products1.xml")) );
Source source = new DOMSource(document);
Result result = new StreamResult(new File(outputFile));

Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(source, result);
          */

        PrintStream psout = new PrintStream(new FileOutputStream("products_out.xml"));
     BufferedReader in = new BufferedReader(new FileReader("MyFile.xml"));
    String str;
            psout.println("<Root>");
    while ((str = in.readLine()) != null) {
        if(str.startsWith("<?xml "))continue;
        if(str.trim().startsWith("<ZQuery"))psout.print(str.trim());
        else psout.println(str.trim());
        
    }
        psout.println("</Root>");
    in.close();
        psout.close();


FileInputStream bais = new FileInputStream("products_out.xml");
  pa.parse(new InputSource(bais));
        for(String s : ReadXMLFile.data){
            System.out.println(s);
        }
  //      pa.parse("products.xml");
       // pa.parse("<ZQuery><![CDATA['This is the cdata']]></ZQuery>");  

        

     } catch (Exception e) {
       e.printStackTrace();
     }

   }

}

Open in new window


Output:

Some Group

SELECT ....


SELECT ....


SELECT ....

Open in new window





0
 

Author Comment

by:snajalm
ID: 36972394
Thanks so much for_yan!  Is it possible for you to make your code in a way so that I could instantiate it passing an XML String to its constructor and have it return the queries in an listArray for me??!  I'm under an extreme time constraint and it would be a great help if you could help me with that.  My XML knowledge is very limited and I'm aiming to boost it right after I get this proj off my shoulder!

I further thank you for your great help at this pressuring stage!
0
 
LVL 47

Accepted Solution

by:
for_yan earned 2000 total points
ID: 36972457
There is static method getMap(xmlString);
It returns HashMap which has txnid attribute value as a key and
and ArrayList of data strings as value (see output test below).

You can remove commented out lines and unused imports if you care about it

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.ParserAdapter;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;


public class ReadXMLFile {

                    static   ArrayList<String>    data;

    static HashMap <String, ArrayList<String>>map;

    static String attrib;

    public static void main(String[]args){

    String xmlString =   "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n" +
            "<ZQueries txnid=\"Some Group\" version=\"1.0.0.0\">\n" +
            "    <ZQuery name=\"some name 1\" savename=\"some_name_1.xml\">\n" +
            "        <![CDATA[\n" +
            "        SELECT ....\n" +
            "        ]]>\n" +
            "    </ZQuery>\n" +
            "    <ZQuery name=\"some name 2\" savename=\"some_name_2.xml\">\n" +
            "        <![CDATA[\n" +
            "        SELECT ....\n" +
            "        ]]>\n" +
            "    </ZQuery>\n" +
            "    <ZQuery name=\"some name 3\" savename=\"some_name_3.xml\">\n" +
            "        <![CDATA[\n" +
            "        SELECT ....\n" +
            "        ]]>\n" +
            "    </ZQuery>\n" +
            "</ZQueries>" +
            "<ZQueries txnid=\"Another Group\" version=\"1.0.0.0\">\n" +
            "    <ZQuery name=\"some name 1\" savename=\"some_name_1.xml\">\n" +
            "        <![CDATA[\n" +
            "        SELECT another 1....\n" +
            "        ]]>\n" +
            "    </ZQuery>\n" +
            "    <ZQuery name=\"some name 2\" savename=\"some_name_2.xml\">\n" +
            "        <![CDATA[\n" +
            "        SELECT another 2....\n" +
            "        ]]>\n" +
            "    </ZQuery>\n" +
            "    <ZQuery name=\"some name 3\" savename=\"some_name_3.xml\">\n" +
            "        <![CDATA[\n" +
            "        SELECT another 3....\n" +
            "        ]]>\n" +
            "    </ZQuery>\n" +
            "</ZQueries>";


                   map = getMap(xmlString);
        /*
        System.out.println("ArrayList: ");
            for(String s : ReadXMLFile.data){
            System.out.println(s);
        }
        */

        System.out.println(map);

        }


    public static HashMap<String, ArrayList<String>> getMap(String xmlString) {

       //   data = new ArrayList<String>();
         map = new HashMap<String, ArrayList<String>>();



    try {

	SAXParserFactory factory = SAXParserFactory.newInstance();
       // factory.setValidating(true);
	SAXParser saxParser = factory.newSAXParser();

	DefaultHandler handler = new DefaultHandler() {

        ArrayList <String>ar;
	boolean bfname = false;
	boolean blname = false;
	boolean bnname = false;
	boolean bsalary = false;

	public synchronized void startElement(String uri, String localName,String qName,
                Attributes attributes) throws SAXException {

		//System.out.println("Start Element :" + qName);

		if (qName.equalsIgnoreCase("ZQuery")) {
			bfname = true;
		}

		if (qName.equalsIgnoreCase("ZQueries")) {
			blname = true;
                      int len = attributes.getLength();
            for(int j=0; j<len; j++){
               // System.out.println(attributes.getLocalName(j));
                if(attributes.getLocalName(j).equals("txnid"))  {
          //      System.out.println(attributes.getValue(j));
                    attrib =  attributes.getValue(j);

                }
            }


            if(map.get(attrib) == null){
                ar = new ArrayList<String>();


            }   else
               ar = map.get(attrib);

		}
          /*
		if (qName.equalsIgnoreCase("NICKNAME")) {
			bnname = true;
		}

		if (qName.equalsIgnoreCase("SALARY")) {
			bsalary = true;
		}
        */

	}

	public synchronized void endElement(String uri, String localName,
		String qName) throws SAXException {
        if(qName.equals("ZQueries")){
            map.put(attrib, ar);
        }

	//	System.out.println("End Element :" + qName);
        

	}

	public synchronized void characters(char ch[], int start, int length) throws SAXException {
       // System.out.println(bfname + ": " +  new String(ch));

		if (bfname) {
            String s =  new String(ch, start, length);
		//	System.out.println("First Name : " + new String(ch, start, length));
          //  ReadXMLFile.data.add(s);
            ar.add(s);
			bfname = false;
		}


		if (blname) {
			//System.out.println("Last Name : " + new String(ch, start, length));
			blname = false;
		}
          /*
		if (bnname) {
		//	System.out.println("Nick Name : " + new String(ch, start, length));
			bnname = false;
		}

		if (bsalary) {
		//	System.out.println("Salary : " + new String(ch, start, length));
			bsalary = false;
		}
        */

	}

     };
         ParserAdapter pa =
 new ParserAdapter(saxParser.getParser());
        pa.setContentHandler(handler);
      // pa.parse("products.xml", handler);
    //    byte bytearray[] = "<ZQuery><![CDATA['This is the cdata']]></ZQuery>".getBytes();
            /*
        String outputFile = "changed.xml";
         DocumentBuilder domparser =
      DocumentBuilderFactory.newInstance().newDocumentBuilder();
         Document document = domparser.parse( new InputSource(new FileInputStream("products1.xml")) );
Source source = new DOMSource(document);
Result result = new StreamResult(new File(outputFile));

Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(source, result);
          */

        PrintStream psout = new PrintStream(new FileOutputStream("products_out.xml"));

       InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(xmlString.getBytes()));
     BufferedReader in = new BufferedReader(reader);
    String str;
            psout.println("<Root>");
    while ((str = in.readLine()) != null) {
        if(str.startsWith("<?xml "))continue;
        if(str.trim().startsWith("<ZQuery"))psout.print(str.trim());
        else psout.println(str.trim());
        
    }
        psout.println("</Root>");
    in.close();
        psout.close();


FileInputStream bais = new FileInputStream("products_out.xml");
  pa.parse(new InputSource(bais));

  //      pa.parse("products.xml");
       // pa.parse("<ZQuery><![CDATA['This is the cdata']]></ZQuery>");  

        

     } catch (Exception e) {
       e.printStackTrace();
     }


   return map;
}
}

Open in new window


Output:

{Another Group=[
SELECT another 1....
, 
SELECT another 2....
, 
SELECT another 3....
], Some Group=[
SELECT ....
, 
SELECT ....
, 
SELECT ....
]}

Open in new window

0
 
LVL 47

Expert Comment

by:for_yan
ID: 36972461
Mind that method takes a string but writes
temporary file during execution
0
 

Author Closing Comment

by:snajalm
ID: 36975788
Thanks for_yan for your valuable and kind help in such a tough time.  I also managed to find out why the casting issue took place in that alternative solutiom.  I just had to setup my iterator like this,

ElementFilter filter = new ElementFilter();
Iterator i = root.getDescendants(filter);

Again thank you a million for supporting us with all these complex technology!
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36976110
Good that it works for you.
You are always welcome.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
This video teaches viewers about errors in exception handling.
Suggested Courses
Course of the Month15 days, 15 hours left to enroll

850 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