# XMLEventReader



## johannes.lichtenberger (6. Okt 2010)

Hallo,

ist es irgendwie möglich den Source auf der eine XMLEventReader-Implementation läuft herauszufinden, also bspw. die Datei? Im Interface ist ja nichts vorgesehen und ansonsten finde ich auch keine Möglichkeit, leider.

Ansonsten muss ich das im Konstruktor einem Callable als Parameter mitgeben, aber irgendwo wär das doppelt gemoppelt:


```
public XMLShredder(final IWriteTransaction paramWtx, final XMLEventReader paramReader,
        final boolean paramAddAsFirstChild, final Object paramData, final boolean paramCommit) throws TreetankUsageException {
        mWtx = paramWtx;
        mReader = paramReader;
        mFirstChildAppend = paramAddAsFirstChild;
        mCommit = paramCommit;
        
        if (paramData instanceof File) {
            mFile = (File)paramData;
        } else if (paramData instanceof XMLEvent[]) {
            mEvents = (XMLEvent[])paramData;
        }
    }
```

und das Dumme ist auch, dass ich aus der call()-Methode des Callables die jeweils passende static-Methode aufrufen muss und static Variablen ja auch nichts in einem Callable zu tun haben sollten, d.h. ich müsste die Methoden kopieren und einmal mit und einmal ohne static modifizierer angebe!? Scheint mir sehr gewagt:


```
/**
     * Create a new StAX reader on a file.
     * 
     * @param paramFile
     *            The XML file to parse.
     * @return an {@link XMLEventReader}.
     * @throws IOException
     *             In case of any I/O error.
     * @throws XMLStreamException
     *             In case of any XML parser error.
     */
    public static synchronized XMLEventReader createReader(final File paramFile) throws IOException,
        XMLStreamException {
        final XMLInputFactory factory = XMLInputFactory.newInstance();
        factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
        final InputStream in = new FileInputStream(paramFile);
        return factory.createXMLEventReader(in);
    }

    /**
     * Create a new StAX reader based on a List of {@link XMLEvent}s.
     * 
     * @param paramEvents
     *            {@link XMLEvent}s.
     * @return an {@link XMLEventReader}.
     * @throws IOException
     *             In case of any I/O error.
     * @throws XMLStreamException
     *             In case of any XML parser error.
     */
    public static synchronized XMLEventReader createListReader(final XMLEvent... paramEvents)
        throws IOException, XMLStreamException {
        return new ListEventReader(Arrays.asList(paramEvents));
    }
```

D.h. ich will einmal von ausen für den Konstruktor die static Methoden aufrufen können und einmal intern Duplikate der Methoden als nicht static. Und der Methodenaufruf soll halt mit den darunterliegenden Datenstrukturen erfolgen (Datei oder ein varargs XMLEvent-Parameter) und jeweils die richtige aufgerufen werden.

Viele Grüße,
Johannes


----------



## Noctarius (6. Okt 2010)

Ich verstehe beide Probleme nicht:
1. Was stört dich daran eine weitere Referenz auf das selbe Object in den Callable zu schieben?
2. Warum haben Methodenaufrufe auf statische Methoden nichts in Callables zu suchen?
3. Hä?


----------



## Tomate_Salat (6. Okt 2010)

Noctarius hat gesagt.:


> 3. Hä?



Dem schließe ich mich an. Was hast du überhaupt vor?! Eine XML einlesen? Erstelle dir eine xsd oder dtd (ich empfehle xsd) zur xml. Daraus generierst du mit dem vorinstallierten tool xjc deine Javaklassen und verwendest das ganze mit dem JAXBContext.

EMF bietet da glaub auch noch gute Möglichkeiten. Auf jeden Fall würde ich mir niemals den Aufwand machen, einen eigenen Parser mit XMLEventReader zu realisieren oO.


----------



## Noctarius (6. Okt 2010)

Japp würde es auch in der Art machen. Wenn du nur ein paar gewisse Tags brauchst kannst du dir auch Lycia anschauen aber ob das, was du da versuchst, der richtige Weg ist, keine Ahnung. Ich versteh das noch nicht ganz wo du hin willst


----------



## Tomate_Salat (6. Okt 2010)

Noctarius hat gesagt.:


> nur ein paar gewisse Tags brauchst


 was sind den gewisse Tags, haben die das gewisse etwas :lol: iwie liest sich das lustig :autsch:


			
				Noctarius hat gesagt.:
			
		

> Ich versteh das noch nicht ganz wo du hin willst


das tut keiner , man kann es nur erahnen.


----------



## Noctarius (6. Okt 2010)

Wenn du z.B. ein Maven POM anschaust, dann weißt du, dass viele Tags nur zur lesbaren Syntax genutzt werden oder um verschiedene Datenbereiche abzutrennen. Daten enthalten aber erst weiter unten in der Hierarchie liegende Tags. Das meinte ich mit "nur gewisse Tags (nämlich die mit Daten) von Interesse".


----------



## Tomate_Salat (6. Okt 2010)

Achso ok danke, jz weis ich, was du mit "gewissen tags" meinst. War vorher nicht so ganz klar (vor allem um die Uhrzeit^^)


----------



## johannes.lichtenberger (6. Okt 2010)

Noctarius hat gesagt.:


> Ich verstehe beide Probleme nicht:
> 1. Was stört dich daran eine weitere Referenz auf das selbe Object in den Callable zu schieben?



Verstehe ich nicht, ich will eine neue Instanz. Mir gehts darum, dass ich einen zweiten StAX-Parser erstmal an die Stelle bringen will, an der der erste StAX-Parser ist (und das innerhalb von einem Callable).



> 2. Warum haben Methodenaufrufe auf statische Methoden nichts in Callables zu suchen?



Das war von mir Blödsinn...

Was ich will ist, dass ich einmal new XMLShredder(mWTX, XMLShredder.createReader(file), false, false); schreiben kann, also eine Instanz eines XMLEventReaders von einer anderen Klasse aus erzeugen und dann innerhalb des Callables nochmal auf der gleichen Datei einen weiteren Parser öffnen und ihn erstmal an die Stelle navigieren wo der alte war... und ich frag mich ob ich dann eben im Konstruktor zweimal "file" angeben muss, einmal für createReader und dann nochmal für eine globale member Variable, die ich dann in call() an die createReader-Methode übergeben kann. Aber ich komme wohl nicht drumrum den Konstruktor mit einem Object parameter zu erweitern, also so:


```
/** File to parse. */
    protected transient File mFile;

    /** Events to parse. */
    protected transient XMLEvent[] mEvents;

    ...

    /**
     * Normal constructor to invoke a shredding process on a existing {@link WriteTransaction}.
     * 
     * @param paramWtx
     *            {@link IWriteTransaction} where the new XML Fragment should be placed.
     * @param paramReader
     *            Parses the XML Fragment.
     * @param paramAddAsFirstChild
     *            If the insert is occuring on a node in an existing tree. <code>false</code> is not possible
     *            when wtx is on root node.
     * @param 
     * @param paramCommit
     *            Determines if inserted nodes should be commited right afterwards.
     * @throws TreetankUsageException
     *             if insertasfirstChild && updateOnly is both true OR if wtx is
     *             not pointing to doc-root and updateOnly= true
     */
    public XMLShredder(final IWriteTransaction paramWtx, final XMLEventReader paramReader,
        final boolean paramAddAsFirstChild, final Object paramData, final boolean paramCommit) throws TreetankUsageException {
        mWtx = paramWtx;
        mReader = paramReader;
        mFirstChildAppend = paramAddAsFirstChild;
        mCommit = paramCommit;
        
        if (paramData instanceof File) {
            mFile = (File)paramData;
        } else if (paramData instanceof XMLEvent[]) {
            mEvents = (XMLEvent[])paramData;
        }
    }
```

Das ist halt schon allein wegen dem instanceof unschön, lässt sich aber denke ich nicht vermeiden wenn ich die darunterliegende Datenstruktur von einem gegebenen XMLEventReader nicht auslesen kann.

Viele Grüße,
Johannes


----------



## Noctarius (6. Okt 2010)

Bitte versuchen mal zu erklären, was du dir von diesem Vorhaben / Vorgehen versprichst.

Es gibt derzeit keinen, mir einleuchtenden Grund, wieso ich 2 Parser an der selben Stelle haben wollte. Klingt irgendwie nach einem Denk- oder Designfehler.


----------



## johannes.lichtenberger (6. Okt 2010)

Ich muss die Descendants prüfen, zwecks eines diff-Verfahrens (zwischen einer richtigen XML-Datei und einer früheren geshredderten Version einer XML-Datei in unserem XML-Datenbanksystem -- geshreddert heist ins interne Encoding gebracht). D.h. sind zwei Knoten unterschiedlich und findet er unter den right-siblings irgendwo einen Knoten, der mit dem gerade geparsten übereinstimmt, samt descendants kann ich davon ausgehen, dass dazwischen alles gelöscht wurde, ansonsten bin ich auf einem Knoten der neu eingefügt werden soll... Naja gibt dann noch ein paar Sonderfälle, aber gut, ich machs jetzt einfach mit dem erweiterten Konstruktor. Ansonsten sehe ich da keine Möglichkeit. Ich muss im Javadoc halt noch festhalten, dass dann ausschließlich ein XMLEventReader auf einer Datei oder mein ListEventReader verwendet werden kann.


----------

