I've done that in a generator thing I've made at work, using plain 
XMLReader factory (code is off course employers property - but I can 
outline the solution)

Problem: you have a string of xml that you need to generate SAX events 
from, the string could be anything like:
   "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<tag>aklsks</tag>",
   "<tag>aslkfkls</tag><tag>laskklfsa</tag>,
   "<tag> aasdflaskj<kkk>fl</kkk>sadkjf </tag>"

The first string is a valid xml document, the second is missing the 
xml-declaration and does not have a single toplevel element, the third one 
is just missing the xml-declaration (does this actually make it an invalid 
xml?)

Fixing the missing xml declaration can be done by:

if (!xmlstring.startsWith("<?xml")) {
   xmlstring = "<?xml encoding=\"iso-8859-1\" version=\"1.0\" ?>" + 
xmlstring;
}

Now if the xmlstring does contain the xml-declaration I would presume it 
is a valid xml document with one top-level element, else I add a toplevel 
element to be sure to have just one, thus fixing both the xml declaration 
and the possible multiple toplevel elements is done by:

if (!xmlstring.startsWith("<?xml")) {
  xmlstring = "<?xml encoding=\"iso-8859-1\" version=\"1.0\" ?><dummy>" + 
xmlstring + "</dummy>";
}

When streaming the SAX Events I will later filter out the toplevel element 
again ;-)

To be able to stream all but the toplevel element, you need a custom 
ContentHandler; it should proxy all events but the startElement and 
endElement of the toplevel tag; I've implemented it in an inner class and 
it goes like:

protected class FilterContentHandler
    implements ContentHandler
{

   private ContentHandler destination;
   private int depth = 0;

   public FilterContentHandler (ContentHandler adestination)
   {
      destination = adestination;
   }

   public void startDocument ()
   {
      depth = 0;
   }

   public void endDocument ()
   {
   }

   public void startElement (....)
   {
      if (depth > 0) {
         destination.startElement (...)
      }
     depth++;
   }

   public void endElement (...)
   {
      depth--;
      if (depth > 0) {
         destination.endElement (...);
      }
   }

   .. and more methods

}

Off course all methods throw the SAXException - methods from the 
ContentHandler interface not listed here just proxy to the destination 
ContentHandler.

Then I instantiate an XMLReader, let contenthandler be the sink of your 
SAX Events:

XMLReader reader = XMLReaderFactory.createXMLReader ();
reader.setContentHandler (new FilterContentHandler (contenthandler));

Make an inputsource:

InputSource inputsource =
   new InputSource (new StringReader (xmlstring);

then just do:

reader.parse (inputsource);


If you need a better example I could spent some of my spare time making 
it, maybe during the weekend.

Regards Jakob



Jakob Dalsgaard
Udvikler
e-mail:   [EMAIL PROTECTED]
Vesterbrogade 149
1620 København V
Tlf.:   70 25 80 30
Fax.: 70 25 80 31






"Luca Morandini" <[EMAIL PROTECTED]>
11/08/02 10:55 AM
Please respond to cocoon-users

 
        To:     <[EMAIL PROTECTED]>
        cc: 
        Subject:        Strings to SAX events


Folks,

 We're in the process of writing a Transformer, which, of course, outputs
SAX
 events... but, in the midst of this stream , we need to insert an
 XML element stored in a string.

 To do this we're groping in the dark trying something like this:

  JaxpParser respParser = new JaxpParser();
  respParser.parse( new InputSource(new StringReader(str)),
          new EmbeddedXMLPipe(contentHandler));

 Which fails giving this:
 org.apache.cocoon.ProcessingException: Failed to execute pipeline.:
 java.lang.ClassCastException
 ...
 Caused by: java.lang.ClassCastException
  at

com.lucamorandini.charts.ChartTransformer.endElement(ChartTransformer.java:6
55)
  at

org.apache.cocoon.components.sax.XMLByteStreamInterpreter.parse(XMLByteStrea
mInterpreter.java:129)
  at

org.apache.cocoon.components.sax.XMLByteStreamInterpreter.deserialize(XMLByt
eStreamInterpreter.java:102)
  at
 org.apache.cocoon.components.pipeline.CachingEventPipeline.process
 (CachingEventPipeline.java:219)
  ... 44 more

 java.lang.ClassCastException
  at

com.lucamorandini.charts.ChartTransformer.endElement(ChartTransformer.java:6
55)
  at

org.apache.cocoon.components.sax.XMLByteStreamInterpreter.parse(XMLByteStrea
mInterpreter.java:129)
  at

org.apache.cocoon.components.sax.XMLByteStreamInterpreter.deserialize(XMLByt
eStreamInterpreter.java:102)
  at
 org.apache.cocoon.components.pipeline.CachingEventPipeline.process
 (CachingEventPipeline.java:219)
  at

org.apache.cocoon.components.pipeline.CachingStreamPipeline.process(CachingS
treamPipeline.java:399)

 The classes we use are:
  org.apache.avalon.excalibur.xml.JaxpParser;
  org.xml.sax.InputSource;
  java.io.StringReader;
  org.apache.cocoon.xml.EmbeddedXMLPipe;

 And the environment is:
  Solaris 5.8
  JDK 1.4.1_01
  Tomcat 4.1.12-LE-jdk14
  Cocoon 2.0.3

 May someone please help us ?

 Thanks in advance,

Piero De Nicola & Luca Morandini


     We are protected from the virus by Norton Antivirus Corporate Edition

---------------------------------------------------------------------
Please check that your question  has not already been answered in the
FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>

To unsubscribe, e-mail:     <[EMAIL PROTECTED]>
For additional commands, e-mail:   <[EMAIL PROTECTED]>





---------------------------------------------------------------------
Please check that your question  has not already been answered in the
FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>

To unsubscribe, e-mail:     <[EMAIL PROTECTED]>
For additional commands, e-mail:   <[EMAIL PROTECTED]>

Reply via email to