Offset berechnen (Java, StAX)

  • Hallo,


    ich möchte mit einem StAX-Parser (sehr ähnlich zu SAX, nur halt als Stream) die Offsets der XML-Elemente im Dokument berechnen. Im Moment nutze ich die

    Code
    getCharacterOffset()

    -Methode, um an die Offsets der Elemente zu kommen. Allerdings zeigen die immer auf das Ende des Elements bzw. StAX-Ereignisses.


    Beispiel:


    * = Character-Pointer für Ereignisse

    Code
    <bsp>*
      <node>* <-- 2. Offset
        Text bla bla bla*
      </node>* <-- 4. Offset
    </bsp>*


    Wenn ich jetzt zum Beispiel <node> ausschneiden möchte, würde ich den 2. und 4. Eventoffset nehmen. Aber leider stimmen die Werte nicht ganz, denn ich erhalte dann nicht "Text bla bla bla</node>" sondern irgendwas ähnliches wie "xt bla bla bla</node></bs"


    Die Offsets sind total verschoben und ich jetzt auch nicht mehr, auf was sich das bezieht.


    /// EDIT
    noch ein Beispiel mit Verschachtelung

    Code
    <bsp>*
      <node>* <-- 2. Offset
        Text bla bla bla*
      </node>* <-- 4. Offset
      <node>* <-- 5. Offset
        <internalNode>* <-- 6. Offset
          blub*
        </internalNode>* <-- 8. Offset
      </node>*
    </bsp>*


    Da StAX eine Unterscheidung zwichen öffnenden Tags und schließenden Tags macht, muss überprüft werden, was der letzte Offset war. Weil wenn ich davon ausgehe, dass das schließende Tag der Beginn eines neuen öffnenden Tags ist, funktioniert die Berechnung für das Beispiel oben nicht mehr, weil <internalNode> direkt auf <node> folgt, ohne dass <node> geschlossen wird.
    /// END OF EDIT


    Wie berechne ich die Offsets, damit ich "<node>Text bla bla bla</node>" erhalte?


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

    Einmal editiert, zuletzt von methodus ()

  • Hi,


    ich kenne Deine Variante jetzt nicht, aber ich verarbeite XML-streams mit dem XMLEventReader.
    Hat den Vorteil, dass der XMLEvent bereits die Dateiposition enthält und so einfach drauf zugegriffen werden kann (unterscheidet auch zwischen Anfang und Ende eines Begriffes).


    hth Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • ich nutze auch XMLEventReader, aber woher bekommst du die Start- und Endoffsets? Ich hab wie gesagt nur Location.getCharacterOffset(), um den Offset zu bekommen. Ich hab bisher noch nicht rausgefunden, wie es anderes gehen könnte.


    Ich würde mich über einen kurzen Hint freuen.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Wenn ich den Beginn eines Tags berechnen möchte, geh ich im Moment so vor:


    mit a = Event.getLocation().getCharacterOffset() den Offset vom Ende des Events ermitteln
    mit b = Event.toString().length() die Länge des Events ermitteln


    BeginOffset = a - b;


    aber es geht immer noch nicht richtig. Wenn ich mir aus dem Originaltext mit den berechneten Werten die Passagen kopieren möchte, erhalte ich ein um etwa 10 Zeichen nach hinten verschobenen Bereich. Wo liegt der Fehler?


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Hi methodus,


    der Push war gut ;)


    Ich hatte den Fred schon wieder vergessen.


    Also zurück zum Topic. Vielleicht habe ich Dein Problem ja mistverstanden?
    Wenn Du schon Event.getLocation().getCharacterOffset() kennst, wird Dir sicher auch bekannt sein, dass in der Location Zeile und Spalte stecken. Was brauchst Du noch?


    Könntest Du vielleicht mal erklären, was Du machen, bzw. rausfinden willst?
    Vielleicht führt ja ein anderer Weg nach Rom ;)


    //Edit:
    Wenn Du magst, kannst Du Dir ja auch mal meinen XMLImporter anschauen.


    //nomml Edit:
    also ich nutze den Offset, bzw. Zeile/Spalte nur für Fehlermeldungen.
    Ich denke nicht, dass die für Auswertungen notwendig sind. Du bekommst doch alles in den Events?!?

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

    2 Mal editiert, zuletzt von geronimo ()

  • Ich will mit dem Parser Teile des Dokuments an eine andere Stelle kopieren, ohne das Dokument wieder rücktransformieren zu müssen.


    Wieso der Umstand? Parsen muss ich sowieso, damit ich mir einen Dokumentenbaum erstellen kann und auch im Dokument selbst navigieren. Wenn ich jetzt mit irgend einem anderen Parser die Teile hin und herkopiere, mag das zwar gehen, aber ich muss dann mindestens zwei Mal parsen: 1x um die Teile zu kopieren und 1x um den Baum aufzuspannen. Das will ich umgehen.


    Im Endeffekt würde mich ja schon reichen, wie der Parser die Offsets bestimmt, damit ich das gegensteuern kann, denn häufig, aber eben nicht immer stimmt der Offset ja! Nur hin und wieder ist ein Versatz von bis zu 10 Zeichen möglich.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Ah jetzt ja.


    Gehe ich recht in der Annahme, dass der zu kopierende Teil eines Dokumentes mehere Tags umfasst?
    Also in dem Falle würde ich persönlich lieber mit regulären Ausdrücken arbeiten - je nach Komplexität der XML-Datei.
    Ich gehe mal stark davon aus, dass die Offset-Differenz mit utf8 zusammen hängt.


    Kennst Du das Digester-Projekt von apache-commons?
    Mit dem kann man fein granulierte XML-Parser aufsetzen und vielleicht geht Dein Vorhaben mit dem Projekt einfacher, als mit XMLEvents?


    Ich habe sowas ähnliches mal mit perl gemacht - kann jetzt aber nicht beurteilen, ob Dein Ausgangsmaterial für reguläre Ausdrücke geeignet ist.


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

    Einmal editiert, zuletzt von geronimo ()

  • Naja, die entsprechenden Teile herauszukopieren würde mit Regexp oder sogar DOM gehen, aber DOM ist für das häufige Parsen zu langsam...


    Das Dokument kann in einem Textfeld editiert werden und soll bei Fokusverlust ausgewertet werden (Dokumentenbaum, usw.), damit das schnell geht, sollen während des Parsens einfach die Teile herauskopiert werden.


    Ich versuch es dann nochmal mit einer Erweiterung vom StringReader, es sei denn, du hast noch eine Idee?


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Moin,


    Zitat

    aber DOM ist für das häufige Parsen zu langsam...


    DOM macht *imho* dann Sinn, wenn man das gesamte XML im Speicher halten will und häufig im Baum navigiert.


    Zitat

    Das Dokument kann in einem Textfeld editiert werden


    Oups - also wenn der Anwender auch die XML-tags eingeben soll, halte ich XML-Mittel zum parsen gänzlich ungeeignet. XML ist eine "wohl geformte" Sprache, d.h. der kleinste Tipsfehler bringt Dein System zum Absturz.


    Wie gesagt: reguläre Ausdrücke, in Zusammenhang mit einem Logikbaum, bzw. State machine. Du suchst mit einem Muster nach den Tags und wertest dann aus, ob die Logik dahinter stimmt. So hast Du stets die ganze Kontrolle.


    Du könntest auch erwägen, Dein Dokument als DOM aufzubauen und nur einzelne Knoten bearbeiten zu lassen. So bräuchtest Du Dich nicht mit Offsets rumärgern, würdest die Kontrolle über die Tags behalten und könntest dynamisch Knoten zufügen, bzw. entfernen.


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Die Sache mit DOM und dem Baum mag sein, aber da ich ihn eh über Swing darstellen lasse, ist ein zusätzliches Zurückhalten nicht notwendig.


    Und das ändern am Quelltext von XML ist kein Problem, da 1. der Parser validierend ist und dadurch 2. der Baum nicht erzeugt wird.


    Ich habe jetzt eine neue Implementation gefunden: StAX2


    zu finden hier:woodstox.codehaus.org


    Die API von Sun selbst ist fehlerhaft und deswegen stimmen die Offsets nicht. In der Woodstox-API werden die Dateizeiger sowohl auf die Byte-Offsets als auch auf die Character-Offsets zurückgehalten, was ein exaktes Navigieren im Code möglich macht.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Moin,


    Danke für den Hinweis!


    Bin bislang noch nicht mit Problemen in Berührung gekommen, aber ich werde mir das Teil auch mal reinziehen.
    //Edit:
    Whow - die unterstützen ein skipEvent - schätze ich muss mir das genauer unter die Lupe nehmen :)


    Gruß Geronimo


    P.S. Mich würde Dein Proggy schonmal interessieren. Vielleicht magst Du ja mal nen Link posten ...

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

    Einmal editiert, zuletzt von geronimo ()

  • Zitat

    Ich habe jetzt eine neue Implementation gefunden: StAX2


    Leider kein Standard und bindet dich für immer an Woodstox.


    Zitat

    Die API von Sun selbst ist fehlerhaft und deswegen stimmen die Offsets nicht.


    Die API oder die Implementierung? Die Implementierung ist hier:
    https://sjsxp.dev.java.net/
    Lade dir da mal die Version 1.0.1 runter und falls damit der Fehler weiter besteht, mach einen Bugreport auf der Webseite auf.


    Ansonsten kannst du natürlich auch einfach Woodstox mit StAX verwenden. Machen wir auch, weil Woodstox schneller ist als SJSXP.


    Ehrlich gesagt habe ich trotzdem nicht ganz verstanden, wozu du überhaupt die Offsets braucht? Willst du das Fragment nicht nur kopieren sondern auch die Formatierung komplett erhalten? Ich persönlich würde XSLT verwenden, genau dafür ist es ja gemacht.

    HFX mini, i3-4330, Asrock H97M, 2 x 2 GB DDR3-1600, OCZ Vertex 32GB, 2 x WDC Caviar Green 2 TB, Pioneer DVR-K06, Terratec Cinergy 1200 DVB-C, TechnoTrend C-1500, YARD mini USB mit OLED, Pulse-Eight USB - HDMI-CEC, Debian Jessie, Kodi

  • Zitat

    Original von geronimo
    P.S. Mich würde Dein Proggy schonmal interessieren. Vielleicht magst Du ja mal nen Link posten ...


    Sourcen kommen sobald sie dokumentiert sind :lol2


    Zum Projekt: Text2Skin-Editor :lovevdr


    fax: richtig, Standard ist es nicht, aber dummerweise funktioniert es damit und ich habe bei StAX2 eine höhere Flexibilität, da einfach mehr Informationen angeboten werden, die mir wichtig sind. Eben diese Offsets zum Beispiel. Diese dienen ja dann nicht nur um Teile aus dem Dokument hin und her zu kopieren, sondern auch später exakt im Dokument Änderungen vorzunehmen ohne das Dokument komplett neu aufzubauen. Ich halte diese Variante für wesentlich schneller, als per Regexp oder DOM das Dokument zu ändern und neu aufzubauen, weil es sich eben um einen Editor handelt. Aber die Idee mit XSLT würde mich trotzdem mal interessieren. Wie genau meinst du das?


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

  • Zitat

    Zum Projekt: Text2Skin-Editor


    Huch - und da arbeitest Du live mit XML?


    Wieso nicht mit Javabeans, die Du einmal importierst und beim Speicheln wieder exportierst?
    Meine Menüthemen bearbeite ich auch so. Hat den Vorteil, dass ich mich beim Editieren um keine Formate kümmern muss und beim Im- und Export kann ich validieren, bzw. noch patchen, wenn's denn notwendig sein sollte.


    Ich finde, Du machst Dir das Leben unnötig schwer - nur so ganz privat am Rande ;)


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Zitat

    Aber die Idee mit XSLT würde mich trotzdem mal interessieren. Wie genau meinst du das?


    Mit XSLT kannst du ein XML Dokument einlesen, beliebig modifizieren und wieder zurückschreiben. Vermutlich ist das insgesamt langsamer als StAX, aber dafür kannst du mit XSLT das gleiche mit wesentlich weniger Code erreichen und bist deutlich flexibler. Das Hauptproblem ist dabei, dass du erst XSLT lernen musst, und das hat eine ziemlich steile Lernkurve.


    Für einen XML Editor würde ich aber vermutlich auch etwas wie geronimo machen und JAXB oder Castor XML oder eines der Dutzend anderen XML Binding Frameworks benutzen.

    HFX mini, i3-4330, Asrock H97M, 2 x 2 GB DDR3-1600, OCZ Vertex 32GB, 2 x WDC Caviar Green 2 TB, Pioneer DVR-K06, Terratec Cinergy 1200 DVB-C, TechnoTrend C-1500, YARD mini USB mit OLED, Pulse-Eight USB - HDMI-CEC, Debian Jessie, Kodi

  • Zitat

    Das Hauptproblem ist dabei, dass du erst XSLT lernen musst,


    Brauch ich nicht, kann ich schon. :lol2


    Ich habe mir mal JAXB und Castor angesehen. Das sieht schonmal sehr gut aus, um die XML-Struktur zu laden, denn ich ganzen Klassen habe ich jetzt manuell erstellt und da könnte man wieder die Integrität der Daten in Frage stellen. Vielleicht geht das mit JAXB eleganter, soll aber an der Stelle noch nicht zum Problem gemacht werden, da es bisher recht gut geht. Den Parser brauche ich leider trotzdem zwecks der Offsets. Jetzt habe ich aber auf der Webseite von JAXB gelesen, dass man die SAX-Events (und sicherlich auch StAX) an JAXB zum unmarshalisieren (geilet Wort :schiel) weiterleiten kann.


    Das würde mir natürlich erstmal ersparen, die Baumintegrität zu garantieren, auch was Kindselemente betrifft.


    Weiß jemand wie weit RelaxNG oder Schematron in Java unterstützt werden? StAX2 kann Schema und RelaxNG, wie ich gelesen habe. Schema kann keine wechselseitigen Ausschlüsse bzw. generell komplexere Strukturen, die mit Bedingungen zusammenhängen. Wenn ich mit JAXB zu 98% sicher gehen will, dass keine Sinnlosigkeiten generiert werden können, wäre eine einfache Überprüfungs/Validierungsmöglichkeit schon toll.


    //edit:

    Zitat

    Original von geronimo


    Huch - und da arbeitest Du live mit XML?


    Schon nen HTML-Editor gesehen, wo man kein HTML selber eingeben kann?


    Die ganze Validierungs- und Parsergeschichte ist im Endeffekt nur deswegen nötig, weil später eine Vorschau generiert werden soll. Das passende JavaBean hab ich wie vorher beschrieben schon erstellt.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

    Einmal editiert, zuletzt von methodus ()

  • Zitat

    Schon nen HTML-Editor gesehen, wo man kein HTML selber eingeben kann?


    Ok - sorry. Scheint als hätte ich den Sinn der Anwendung falsch verstanden.


    Ich dachte, der Editor wäre für VDR-Anwender, die ein OSD-Skin erstellen wollen.
    Wenn ich mir jetzt so einen Anwender vorstelle, bzw. mich in so eine Rolle reindenke, dann interessiert mich nicht im Geringsten, in welchem Format ein Skin verarbeitet wird.
    Als ein solcher Anwender wollte ich OSD-Elemente bearbeiten, vielleicht auch Farben und/oder Größe verändern, etc.
    In einem solchen Falle würde mich interessieren, welche Elemente im OSD unterstützt werden und welche Eigenschaften ich im Skin verändern kann.
    Wieso sollte ich mich für das "interne Format" der Skinverarbeitung interessieren wollen? Wenn es mich denn interessiert, könnte ich mir immer noch das Plugin reinziehen.
    Das interne Format könnte sich in späteren Versionen ja auch ändern - und dann muss jeder wat neuet lernen. Wäre aba dumm - nicht?


    Wenn Du Dir jetzt mal XML nur als Schnittstelle zum Speichern vorstellst, könntest Du das ganze Dokumenten Gedöns mit Offset und Schnickschnack in die Tonne kicken und nen schicken GUI-Editor basteln - so hätte ich mir das zumindest vorgestellt ...


    ... das heißt aba noch lange nicht, dass ich von irgendwas ne Ahnung hätte.


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Zitat

    Den Parser brauche ich leider trotzdem zwecks der Offsets. Jetzt habe ich aber auf der Webseite von JAXB gelesen, dass man die SAX-Events (und sicherlich auch StAX) an JAXB zum unmarshalisieren (geilet Wort :schiel) weiterleiten kann.


    Ich habe noch immer nicht kapiert, was du da genau machst, aber egal. Übrigens, es heißt entmarscheln. Oder war es entbinden? :unsch


    Zitat

    Weiß jemand wie weit RelaxNG oder Schematron in Java unterstützt werden? StAX2 kann Schema und RelaxNG, wie ich gelesen habe. Schema kann keine wechselseitigen Ausschlüsse bzw. generell komplexere Strukturen, die mit Bedingungen zusammenhängen. Wenn ich mit JAXB zu 98% sicher gehen will, dass keine Sinnlosigkeiten generiert werden können, wäre eine einfache Überprüfungs/Validierungsmöglichkeit schon toll.


    Der Autor von JAXB ist auch eine der Hauptpersonen hinter Relax NG, das müsste also eigentlich gut flutschen.

    HFX mini, i3-4330, Asrock H97M, 2 x 2 GB DDR3-1600, OCZ Vertex 32GB, 2 x WDC Caviar Green 2 TB, Pioneer DVR-K06, Terratec Cinergy 1200 DVB-C, TechnoTrend C-1500, YARD mini USB mit OLED, Pulse-Eight USB - HDMI-CEC, Debian Jessie, Kodi


  • Das Ding ist, dass das eigentlich geplant ist. Also, dass man über ein Toolkit sich bestimmte Elemente zusammenklickt und am Ende ein schöner Skin rauskommen soll. ABER: eigene Erfahrungen haben gezeigt, dass WYSIWYG-Editoren sehr häufig Mist produzieren und ich deswegen lieber mehr Zeit in eine ordentliche XML-Darstellung und Bearbeitung investieren möchte, als in eine verkorkste Klickibunti-Anwendung. Das Endergebnis ist trotzdem die Klickbunti-Anwendung, aber mit dem Fallback auf händische Ingenieurskunst: Do-It-Yourself.


    Das sich am Skin-Format was ändern kann, okay. Dass die Leute dann ständig was neues lernen müssen auch ok. Aber der Editor kann dann wenigstens noch im Groben genutzt werden auch wenn die neuen Skin-Versionen nicht unterstützt werden, was fehlt ist die entsprechende Preview- bzw. Editorfunktion, aber alles andere geht dann noch! Man muss sich ja immer Gedanken machen "Ist meine Software noch lauffähig, wenn sich etwas geringfügig ändert?!". Wenn das Schema nicht mehr matcht und daher kein Baum generiert werden kann und somit keine Editorfunktionen nutzbar sind, nein. Wenn der Editor unabhängig davon ist, schon.


    //Edit: im übrigen ist das Testen der Vorschau und Editorfunktion so, wie ich es im Moment geplant habe, wesentlich einfacher, denn ich sehe ja im Codeeditor schon den generierten Quelltext und weiß bevor ich exportiere, was er zusammenschmeißt.


    Medion Digitainer; AsRock B75 Pro3-M, Celeron G540; Kingston Value 4GB
    Samsung SpinPoint 250GB 2,5"; Samsung WriteMaster DVD-Brenner;
    TT-S2-6400, 2x TT-S2-1600, Ubuntu 12.04 mit YaVDR-Paketen. VDR 1.7.27, UPnP/DLNA-Plugin

    Einmal editiert, zuletzt von methodus ()

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!