# Mal wieder Sax was sonst ;(



## spike78 (7. Sep 2006)

Hi zusammen,

ich kämpfe mal wieder mit dem SAX Parser rum. Ich lese eine XML Datei ein und speichere mir meine Attribute und den dazugehörigen Wert in einer HashMap.

zB.

<event>
  <attribute type="TESTACTIONS-TACT_ID">28580</attribute>
  <attribute type="PROTOCOLS-PRC_NEW_VALUE">5</attribute>
  <attribute type="PROTOCOLS-PRC_FIELD">TACT_REV_ID</attribute>
  <attribute type="TESTACTIONS-TACT_TEST_JAVA_ID">JRE_14203      </attribute>


Attribut: TESTACTIONS-TACT_TEST_JAVA_ID
Wert    : JRE_14203

Zum Speichern der Werte verwende ich:


```
public void characters(char[] c, int start, int length)    throws SAXException
    {
        String sValue = new String(c, start, length);
        try {
            valueint = new Integer(sValue);
            //value=valueint.toString().getBytes();

        }catch (NumberFormatException ex) {
            // kein Integer möglich
            valueint = null;
            value =sValue.trim();
        }
        sValue="";
    }
```

Zunächst geht alles gut, aber wenn die Datei etwas größer ist (6MB - Sollte ja kein Problem darstellen), verschluckt die Methode einige Buchstaben. So steht z.B für "JRE_14203" dann nur noch "03" drin.  Woran kann das liegen? Kommt der Parser etwas bei größeren Dateien durcheinander ?

Gruß

Michael


----------



## Roar (7. Sep 2006)

characters() kann mehrmals für einen text aufgerufen werden. vermutlich verschluckst du einfach das erste mal und speicherst nur den zweiten wert ab.


----------



## spike78 (7. Sep 2006)

Das Problem schein zu sein, dass in dem Array "c" der Wert gepuffert drin steht. Und genau an dieser Stelle liest er nur QP und beim nächsten mal das V aus.



Beispiel:

1. Aufruf :
  <attribute type="PROTOCOLS-PRC_USRROLE_ID">QP

2. Aufruf

 <attribute type="PROTOCOLS-PRC_USRROLE_ID">QPV </attribute>

Beim esten mal nimmt er sich nur QP. Wie bekomm ich denn aber das QPV daraus ?

Gruß


----------



## Gelöschtes Mitglied 5909 (7. Sep 2006)

Dazu paste ich einfach mal einen teil von ner folie vom prof

• Note
– Content of elements may be passed with multiple calls to character(),
e.g. when content is lengthy or contains entity references
– Entity references only resolved when DTD is used (with Entity
declaration)
– ch.length may be greater than length or startIndex greater than zero due
to optimizations of SAX parser
– Behavior depends on SAX parser used
<name>a very long name & and here comes the end</name>
1st call of characters(): “a very long name”
2nd call of characters(): “AREF”
3rd call of characters(): “here comes the end”

Wenn ich mich nich täusch sollte des mit nem StringBuffer + .append() einfach zu regeln sein


----------



## spike78 (7. Sep 2006)

Hi,

kannst Du mir das mal in einem Beispiel zeigen. Sorry aber ich hab noch nicht so die Erfahrung damit.

Gruß


----------



## huckfinn (20. Sep 2006)

Hi, 
Tschuldigung daß ich mich hier so naßforsch einmische, aber ich 
habe gerade eine passende Kodeschnipslette.
Es ist in der Tat so, daß du die einzelnen Textblöcke in der Methode 

```
public void characters(char[] ch, int start, int length) throws SAXException ...
```
zusammensammeln muß. Das hängt damit zusammen, daß diese für 
die Auflösung von Whitespaces, Entities, Zeilenumbrüche etc. verlassen wird.

Ich schick dir mal einen kleinen Beispielscanner mit, der ein XML 
Web-Protololl folgender Form einliest:

```
<server-response>

     <identify responseID="ident">
         <param-list>
                   <param name="sessionID" value="ID1"/>
                   <param name="requestID" value="ID2"/>
         </param-list>
     </identify>
     
     <error type="type" code="code">
         Wie du siehst kommt hier Text rein!
     </error>

     <echo>
         Wie du siehst kommt hier Text rein!
     <echo>
    
<server-response>
```

Ich verwende einen Stack, um mitzuschreiben , 
ob die Methode 
	
	
	
	





```
characters(char[]..
```
irgendwas einsammeln soll. Das geschieht in der Methode 

```
public void startElement(String uri,..
```
klar wo sonst. Ein Beispiel dafür ist der Error bzw. Echo Modus 
des Scanners:

```
} else if (localName.equals(Config.XML_SHELL_ECHO)) {
             checkMode(PARSE_SHELL_RESPONSE);
             parseMode.push(new Integer(PARSE_ECHO_MODE));
             echo = new StringBuffer(); 

        } else if (localName.equals(Config.XML_SHELL_ERROR)) {
             checkMode(PARSE_SHELL_RESPONSE);
             parseMode.push(new Integer(PARSE_ERROR_MODE));
             errorName=XML.getAttribute(atts,Config.XML_SHELL_ERROR_CMD);
             errorType=XML.getAttribute(atts,Config.XML_SHELL_ERROR_TYPE);
             error = new StringBuffer();
             isError=true;
          .......
```

Wie du siehst werden auch gleich Kollektoren in Form von StringBuffern 
initialisiert. Das Einsammeln läuft dann wie folgt:


```
public void characters(char[] ch, int start, int length) throws SAXException {
        int mode = getMode();
        if (mode==PARSE_ECHO_MODE) {
          String data = new String(ch,start,length);
          echo.append(data);
        } else if (mode==PARSE_ERROR_MODE) {
          String data = new String(ch,start,length);
          error.append(data);
        } else if (mode==PARSE_FILE_CNT_MODE) {
          String data = new String(ch,start,length);
          fileData.append(data.trim());
        }
    }
```
 
Ich schick dir mal den Code für den Scanner mit ..du kannst 
ihn ja zum Testen abspecken.

Als denne Huck


```
------------------------- SNIPP SNIPP -------------------------
package de.uag.util;

/**
* Definition der String Konstanten
 * @author huckfinn
 */
public class Config {

    public static final String XML_IDENTIFY             = "identify";
    public static final String XML_IDENTIFY_REMOTE_HOST = "remoteHost";
    public static final String XML_IDENTIFY_REMOTE_PORT = "remotePort";
    public static final String XML_IDENTIFY_REMOTE_USER = "remoteUser";
    public static final String XML_IDENTIFY_SERVER_HOST = "serverHost";
    public static final String XML_IDENTIFY_SERVER_PORT = "serverPort";
    public static final String XML_IDENTIFY_SERVLET_ID  = "servletID";
    public final static String XML_IDENTIFY_SESSION_ID  = "sessionID";
    public final static String XML_IDENTIFY_REQUEST_ID  = "requestID";
    public final static String XML_IDENTIFY_RESPONSE_ID = "responseID";
    
    public static final String XML_DIRECTORY       = "directory";
    public static final String XML_DIRECTORY_LIST  = XML_DIRECTORY+"-list";
    public static final String XML_DIRECTORY_PATTERN  ="pattern";
    public static final String XML_DIRECTORY_NAME  = "name";
    public static final String XML_DIRECTORY_DATE  = "date";
    public static final String XML_DIRECTORY_TIME  = "time";
    public static final String XML_DIRECTORY_ROOT  = "root";
    public static final String XML_DIRECTORY_OWNER = "edit";
    public static final String XML_DIRECTORY_WORLD = "other";
    
    public static final String XML_FILE       = "file";
    public static final String XML_FILE_LIST  = XML_FILE+"-list";
    public static final String XML_FILE_PATTERN  ="pattern";
    public static final String XML_FILE_NAME  = "name";
    public static final String XML_FILE_DATE  = "date";
    public static final String XML_FILE_TIME  = "time";
    public static final String XML_FILE_SIZE  = "size";
    public static final String XML_FILE_TYPE  = "type";
    public static final String XML_FILE_ROOT  = "root";
    public static final String XML_FILE_OWNER = "edit";
    public static final String XML_FILE_WORLD = "other";
    public static final String XML_FILE_CONTENT="file-content";    

    public static final String XML_SHELL_RESPONSE="shell-response";
    public static final String XML_SHELL_ERROR="error";
    public static final String XML_SHELL_ERROR_CMD="command";
    public static final String XML_SHELL_ERROR_TYPE="type";
    public static final String XML_SHELL_ECHO="echo";
    public static final String XML_SHELL_PARAM_LIST="parameter-list";
    public static final String XML_SHELL_PARAM="parameter";
    public static final String XML_SHELL_PARAM_NAME="name";
    public static final String XML_SHELL_PARAM_VALUE="value";
    
}

------------------------- SNIPP SNIPP -------------------------
package de.uag.client;

import de.uag.util.Config;
import de.uag.util.StrUtils;
import de.uag.util.XML;
import java.io.*;
import java.util.*;
import org.apache.commons.codec.binary.Base64;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;

/**
 * XML Scanner für das WEB Protokolll
 * @author huckfinn
 */
public class ServerResponse implements ContentHandler {
    final static int PARSE_SHELL_RESPONSE  =  0;
    final static int PARSE_IDENTIFY_MODE   = 10;
    final static int PARSE_PARAMETER_LIST_MODE  = 20;
    final static int PARSE_PARAMETER_MODE  = 25;
    final static int PARSE_ECHO_MODE       = 30;
    final static int PARSE_ERROR_MODE      = 40;
    final static int PARSE_OPEN_FILE_MODE  = 50;
    final static int PARSE_LIST_FILES_MODE = 60;
    final static int PARSE_LIST_DIRS_MODE  = 70;
    final static int PARSE_FILE_ENTRY_MODE = 80;
    final static int PARSE_DIR_ENTRY_MODE  = 90;
    final static int PARSE_FILE_CNT_MODE   = 100;
    
    //--------------------------------------------------------------------------
    Stack parseMode = new Stack();
    String errorName = null;
    String errorType = null;
    StringBuffer error  = null;
    //--------------------------------------------------------------------------
    StringBuffer echo   = null;
    //--------------------------------------------------------------------------
    ArrayList files     = null;
    String filesPattern = null;
    //--------------------------------------------------------------------------
    ArrayList dirs      = null;
    String dirsPattern  = null;
    //--------------------------------------------------------------------------
    TreeMap parameter   = null;
    //--------------------------------------------------------------------------
    String sessionID    = null;    
    String requestID    = null;
    String responseID   = null;
    //--------------------------------------------------------------------------
    StringBuffer fileData = null;
    FileEntry fileStat  = null;
    byte[] fileContent  = null;
    //--------------------------------------------------------------------------
    boolean isShellResponse = false;
    boolean isRootTag       = false;
    boolean isFinished      = false;
    boolean isError         = false;
    //--------------------------------------------------------------------------
    private  org.apache.xerces.parsers.SAXParser parser = null;
    private  org.xml.sax.InputSource dataSource = null;
    private  InputStream xmlStream = null;
    
    
    //--------------------------------------------------------------------------
    /** Creates a new instance of ClientShellParser */
    public ServerResponse() {
        super();
        parser = new org.apache.xerces.parsers.SAXParser();
        
    }
    
    //--------------------------------------------------------------------------
    public void parse(InputStream inputStream) throws SAXException {
        try {
            xmlStream = inputStream;
            parser.setFeature("http://xml.org/sax/features/validation",false);
            parser.setFeature("http://apache.org/xml/features/" +
                                  "nonvalidating/load-external-dtd",false);
            parser.setContentHandler(this);
            dataSource = new InputSource(xmlStream);
            parser.parse(dataSource);
            
        } catch (Exception e) {
           throw new SAXException("Kann den Datenstrom nicht öffnen! " +
                   "Details:"+e.getMessage());
        }     
    }
    
    //--------------------------------------------------------------------------
    public void setDocumentLocator(Locator locator) {}

    //--------------------------------------------------------------------------
    public void startDocument() throws SAXException {
        String errorName = null;
        String errorType = null;
        String       error  = null;
        String       echo   = null;
        ArrayList files     = null;
        ArrayList dirs      = null;
        TreeMap parameter   = null;
        String sessionID    = null;
        String requestID    = null;
        String responseID   = null;
        String file         = null;
        FileEntry fileStat  = null;
        byte[] fileContent  = null;
        isRootTag           = false;
    }
    
    //--------------------------------------------------------------------------
    public void endDocument() throws SAXException { 
        try {
            xmlStream.close();
            sessionID = getParameter(Config.SHELL_SESSION_ID);
            requestID = getParameter(Config.SHELL_REQUEST_ID);
        } catch (IOException ex) {
            throw new SAXException("ClientShell Parser Fehler!" +
                    " Details: "+ex.getMessage());
        }
         isFinished = true; 
    }
    
    //--------------------------------------------------------------------------
    public void startPrefixMapping(String prefix, String uri)
    throws SAXException {
        throw new SAXException("PrefixMapping is not implemented in "+getClass());
    }
    //--------------------------------------------------------------------------
    public void endPrefixMapping(String prefix) throws SAXException {
        throw new SAXException("PrefixMapping is not implemented in "+getClass());
    }
    
    //--------------------------------------------------------------------------
    public int getMode() throws SAXException {
      Integer lastMode  = (Integer) parseMode.lastElement();
      if (lastMode==null) throw new SAXException("Unbekanter Scanmodus!");
      return lastMode.intValue();
    }
    //--------------------------------------------------------------------------
    public void checkMode(int parentKey) throws SAXException {
      Integer lastMode  = (Integer) parseMode.lastElement();
      if (lastMode==null||lastMode!=parentKey) 
                          throw new SAXException("Falsches Elternelement!");
    }
    //--------------------------------------------------------------------------
    public void startElement(String uri,
            String localName,
            String qName,
            Attributes atts) throws SAXException {

        if (localName.equals(Config.XML_SHELL_RESPONSE)) { 
             isShellResponse=!isRootTag; 
             isRootTag=true;
             parseMode.push(new Integer(PARSE_SHELL_RESPONSE));

        } else if (localName.equals(Config.XML_IDENTIFY)) {
             checkMode(PARSE_SHELL_RESPONSE);
             responseID=XML.getAttribute(atts,Config.XML_IDENTIFY_RESPONSE_ID);
             parseMode.push(new Integer(PARSE_IDENTIFY_MODE));

        } else if (localName.equals(Config.XML_SHELL_PARAM_LIST)) {
             checkMode(PARSE_IDENTIFY_MODE);
             parseMode.push(new Integer(PARSE_PARAMETER_LIST_MODE));
             parameter = new TreeMap();

        } else if (localName.equals(Config.XML_SHELL_PARAM)) {
            checkMode(PARSE_PARAMETER_LIST_MODE);
            parseMode.push(new Integer(PARSE_PARAMETER_MODE));
            String name=XML.getAttribute(atts,Config.XML_SHELL_PARAM_NAME);
            String value = null;
            try {
              value=XML.getAttribute(atts,Config.XML_SHELL_PARAM_VALUE);
            } catch (Exception e) {
              value="**null**";
            } 
            parameter.put(name,value);

        } else if (localName.equals(Config.XML_SHELL_ECHO)) {
             checkMode(PARSE_SHELL_RESPONSE);
             parseMode.push(new Integer(PARSE_ECHO_MODE));
             echo = new StringBuffer(); 

        } else if (localName.equals(Config.XML_SHELL_ERROR)) {
             checkMode(PARSE_SHELL_RESPONSE);
             parseMode.push(new Integer(PARSE_ERROR_MODE));
             errorName=XML.getAttribute(atts,Config.XML_SHELL_ERROR_CMD);
             errorType=XML.getAttribute(atts,Config.XML_SHELL_ERROR_TYPE);
             error = new StringBuffer();
             isError=true;

        } else if (localName.equals(Config.XML_FILE_LIST)) {
             checkMode(PARSE_SHELL_RESPONSE);
             parseMode.push(new Integer(PARSE_LIST_FILES_MODE));
             files = new ArrayList();
             filesPattern = XML.getAttribute(atts,Config.XML_FILE_PATTERN);
             
        } else if (localName.equals(Config.XML_DIRECTORY_LIST)) {
             checkMode(PARSE_SHELL_RESPONSE);
             parseMode.push(new Integer(PARSE_LIST_DIRS_MODE));
             dirs = new ArrayList();
             dirsPattern = XML.getAttribute(atts,Config.XML_DIRECTORY_PATTERN);
             
        } else if (localName.equals(Config.XML_DIRECTORY)) {
             checkMode(PARSE_LIST_DIRS_MODE);
             parseMode.push(new Integer(PARSE_DIR_ENTRY_MODE));
             DirEntry entry = new DirEntry();
             entry.parseXML(atts);
             dirs.add(entry);

        } else if (localName.equals(Config.XML_FILE)) {
             checkMode(PARSE_LIST_FILES_MODE);
             parseMode.push(new Integer(PARSE_FILE_ENTRY_MODE));
             FileEntry entry = new FileEntry();
             entry.parseXML(atts);
             files.add(entry);
             
        } else if (localName.equals(Config.XML_FILE_CONTENT)) {
             checkMode(PARSE_SHELL_RESPONSE);
             parseMode.push(new Integer(PARSE_FILE_CNT_MODE));
             FileEntry file = new FileEntry();
             file.parseXML(atts);
             fileData = new StringBuffer();
        } else 
            throw new SAXException("Unbekanntes Tag \""+localName+"\" !"); 
    }
    
    //--------------------------------------------------------------------------
    public void endElement(String uri,
            String localName,
            String qName) throws SAXException {
        if (getMode()==PARSE_ECHO_MODE) echo.append("\n");
        if (getMode()==PARSE_ERROR_MODE) error.append("\n");
        if (getMode()==PARSE_FILE_CNT_MODE) {
          fileContent=Base64.decodeBase64(fileData.toString().getBytes());        
        }
        parseMode.pop();
    }
    //--------------------------------------------------------------------------
    public void characters(char[] ch, int start, int length) throws SAXException {
        int mode = getMode();
        if (mode==PARSE_ECHO_MODE) {
          String data = new String(ch,start,length);
          echo.append(data);
        } else if (mode==PARSE_ERROR_MODE) {
          String data = new String(ch,start,length);
          error.append(data);
        } else if (mode==PARSE_FILE_CNT_MODE) {
          String data = new String(ch,start,length);
          fileData.append(data.trim());
        }
    }
    
    //--------------------------------------------------------------------------
    public void ignorableWhitespace(char[] ch, int start, int length)
    throws SAXException { // nothing to do 
    }
    
    //--------------------------------------------------------------------------
    public void processingInstruction(String target, String data)
    throws SAXException {}
    
    //--------------------------------------------------------------------------
    public void skippedEntity(String name) throws SAXException {}
    
    //--------------------------------------------------------------------------
    public void dump() {
        System.out.println("PARAMETER:");
        System.out.println("----------");
        StrUtils.listVariables(parameter);
        System.out.println("");
        if (echo!=null) {
          System.out.println("ECHO:");
          System.out.println("-----");
          System.out.println(echo.toString());
          System.out.println("");
        } 
        if (isError) {
          System.out.println("ERROR:");
          System.out.println("------");
          System.out.println("NAME: "+errorName);
          System.out.println("TYPE: "+errorType);
          System.out.println("DETAILS:"+error.toString());     
          System.out.println("");
        }
        if (files!=null) {
          System.out.println("FILELIST:");
          System.out.println("---------");
            for (Iterator it = files.iterator(); it.hasNext();) {
                FileEntry elem = (FileEntry) it.next();
                System.out.println(elem.toString());
            }
          System.out.println("");
        }    
        if (dirs!=null) {
          System.out.println("DIRLIST:");
          System.out.println("---------");
          for (Iterator it = dirs.iterator(); it.hasNext();) {
              DirEntry elem = (DirEntry) it.next();
              System.out.println(elem.toString());
          }
          System.out.println("");
        }    
        if (fileStat!=null) {
          System.out.println("FILE:");
          System.out.println("-----");
          int len = fileContent.length;
          if (len>20) len=20;
          System.out.println(new String(fileContent,0,len-1)+"...");
          System.out.println("");
        }
    }
    
    //--------------------------------------------------------------------------
    public String getError() { return error.toString(); }
    
    //--------------------------------------------------------------------------
    public String getParameter(String ident) { 
         return StrUtils.findVariable(parameter,ident) ;
    }
    //--------------------------------------------------------------------------
    public String getSessionID(){ return sessionID;  }

    public String getResponseID() {  return responseID; }
    //--------------------------------------------------------------------------
    public String getRequestID(){ return requestID;  }
    
    
}
```


----------

