Link to home
Start Free TrialLog in
Avatar of snajalm
snajalm

asked on

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

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

Avatar of for_yan
for_yan
Flag of United States of America image

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
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
Avatar of snajalm
snajalm

ASKER

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

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
Avatar of snajalm

ASKER

I have renamed some of the fields for security reasons but the attached is the exact code I'm getting! myFile.xml
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





Avatar of snajalm

ASKER

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!
ASKER CERTIFIED SOLUTION
Avatar of for_yan
for_yan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Mind that method takes a string but writes
temporary file during execution
Avatar of snajalm

ASKER

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!
Good that it works for you.
You are always welcome.