XML effizient analysieren

Programmierung unter AOO/LO (StarBasic, Python, Java, ...)

Moderator: Moderatoren

Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

XML effizient analysieren

Beitrag von Stephan »

Hallo,

ich möchte in einer (bereits separat im Dateisystem gespeicherten) content.xml-Datei (aus Textdokument, *.odt) bestimmte Abschnitte finden und separieren (z.B. in einer Variable speichern) um sie nachfolgend bearbeiten zu können.

Der Aufbau der content.xml-Datei entspricht dem einer völlig üblichen content.xml eines odt-Dokuments, mit der Besonderheit das u.A. in diesem Dokument "an der Seite" verankerte Textrahmen vorhanden sind.

Schematisch ist der Aufbau innerhalb des body-bereichs der content.xml also ungefähr so:

<office:body>
<office:text [...] >
<!-- Abschnitt A -->
<text:sequence-decls>
[...]
</text:sequence-decls>
<text:user-field-decls>
[...]
</text:user-field-decls>
[...]
<!----------------->

<!-- Abschnitt B -->
<draw:frame [...]>
[...]
</draw:frame>
[...]
<!----------------->

<!-- Abschnitt C -->
<text:p [...]>
[...]
</text:p>
[...]
<!----------------->
</office:text>
</office:body>

"Abschnitt A" und "Abschnitt C" interessieren vorerst nicht.

In "Abschnitt B" müssen alle "<draw:frame [...]> [...] </draw:frame>" gefunden und zur weiteren Bearbeitung zwischengespeichert werden.
Der Beginn von "Abschnitt B" ist begrenzt durch das erste Auftauchen von "<draw:frame [...]>" und das Ende ist unmittelbar vor dem ersten Aufttauchen von "<text:p [...]>" (auf gleicher Hirarchieebene wie "<draw:frame [...]>").

Hinweis: es genügt nicht alle "<draw:frame [...]> [...] </draw:frame>" zu finden, denn solche Tags können auch in "Abschnitt C" vorhanden sein, gesucht sind jedoch nur diejenigen aus "Abschnitt B".


Wer hat Ideen?


Ziel ist es die zwischengespeicherten Teile "<draw:frame [...]> [...] </draw:frame>" anschliessend zu bearbeiten und danach die content.xml, unter Benutzung der earbeiteten Teile, wieder 'zusammenzusetzen' - das aber nur als Erläuterung es geht zunächst nur um die o.g. Aufgabe.


Ich habe bereits folgenden Thread gefunden:
viewtopic.php?t=62289

komme damit jedoch nicht wirklich weiter.



Gruß
Stephan


P.S.
Hier ist ein Beispiel für eine komplette content.xml die meinen 'Anforderungen' entspricht, wobei nochmal gesagt sei das es sich eigentlich um eine völlig übliche content.xml handelt. Die zu findenden Abschnitte (in der konkreten Datei hier sind das 2 Abschnitte) sind verschiedenfarbig hervorgehoben:

<?xml version="1.0" encoding="UTF-8"?>
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" office:version="1.2" grddl:transformation="http://docs.oasis-open.org/office/1.2/x ... :font-face style:name="Mangal1" svg:font-family="Mangal"/><style:font-face style:name="Times New Roman" svg:font-family="&apos;Times New Roman&apos;" style:font-family-generic="roman" style:font-pitch="variable"/><style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/><style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="Microsoft YaHei" svg:font-family="&apos;Microsoft YaHei&apos;" style:font-family-generic="system" style:font-pitch="variable"/><style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/></office:font-face-decls><office:automatic-styles><style:style style:name="P1" style:family="paragraph" style:parent-style-name="Frame_20_contents" style:master-page-name=""><style:paragraph-properties style:page-number="auto" fo:break-before="page"/></style:style><style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame"><style:graphic-properties style:vertical-pos="from-top" style:vertical-rel="page" style:horizontal-pos="from-left" style:horizontal-rel="page" fo:background-color="#ffff00" style:background-transparency="0%"><style:background-image/></style:graphic-properties></style:style><style:style style:name="fr2" style:family="graphic" style:parent-style-name="Frame"><style:graphic-properties style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph"/></style:style><style:style style:name="fr3" style:family="graphic" style:parent-style-name="Graphics"><style:graphic-properties style:run-through="foreground" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="from-top" style:vertical-rel="page" style:horizontal-pos="from-left" style:horizontal-rel="page" style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/></style:style></office:automatic-styles><office:body><office:text text:use-soft-page-breaks="true"><text:sequence-decls><text:sequence-decl text:display-outline-level="0" text:name="Illustration"/><text:sequence-decl text:display-outline-level="0" text:name="Table"/><text:sequence-decl text:display-outline-level="0" text:name="Text"/><text:sequence-decl text:display-outline-level="0" text:name="Drawing"/></text:sequence-decls><draw:frame draw:style-name="fr1" draw:name="Rahmen1" text:anchor-type="page" text:anchor-page-number="1" svg:x="7.86cm" svg:y="5.519cm" svg:width="4.838cm" svg:height="3.006cm" draw:z-index="0"><draw:text-box><text:p text:style-name="Frame_20_contents"><text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="Anrede" text:database-name="Neue Datenbank3"><Anrede></text:database-display></text:p><text:p text:style-name="Frame_20_contents"><text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="Vorname" text:database-name="Neue Datenbank3"><Vorname></text:database-display><text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="Name" text:database-name="Neue Datenbank3"><Name></text:database-display></text:p><text:p text:style-name="Frame_20_contents"><text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="Strasse" text:database-name="Neue Datenbank3"><Strasse></text:database-display></text:p><text:p text:style-name="Frame_20_contents"><text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="PLZ" text:database-name="Neue Datenbank3"><PLZ></text:database-display> <text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="Ort" text:database-name="Neue Datenbank3"><Ort></text:database-display></text:p></draw:text-box></draw:frame><draw:frame draw:style-name="fr3" draw:name="Grafik1" text:anchor-type="page" text:anchor-page-number="1" svg:x="12.966cm" svg:y="3.625cm" svg:width="1.789cm" svg:height="1.143cm" draw:z-index="2"><draw:image xlink:href="Pictures/10000000000004000000030010393590.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/></draw:frame><text:p text:style-name="P1"><text:bookmark text:name="jms-anfang"/><text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="Name" text:database-name="Neue Datenbank3"><Name></text:database-display></text:p><text:p text:style-name="Standard">Er hörte leise Schritte hinter sich. Das bedeutete nichts Gutes. Wer würde ihm schon folgen, spät in der Nacht und dazu noch in dieser engen Gasse mitten im übel beleumundeten Hafenviertel? Gerade jetzt, wo er das Ding seines Lebens gedreht hatte und mit der Beute verschwinden wollte! Hatte einer seiner zahllosen Kollegen dieselbe Idee gehabt, ihn beobachtet und abgewartet, um ihn nun um die Früchte seiner Arbeit zu erleichtern? Oder gehörten die Schritte hinter ihm zu einem der unzähligen Gesetzeshüter dieser Stadt, und die stählerne Acht um seine Handgelenke würde gleich zuschnappen? Er konnte die Aufforderung stehen zu bleiben schon hören. Gehetzt sah er sich um. Plötzlich erblickte er den schmalen Durchgang. </text:p><text:p text:style-name="Standard">Blitzartig drehte er sich nach rechts und verschwand zwischen den beiden Gebäuden. Beinahe wäre er dabei über den umgestürzten Mülleimer gefallen, der mitten im Weg lag. Er versuchte, sich in der Dunkelheit seinen Weg zu ertasten und erstarrte: Anscheinend gab es keinen anderen Ausweg aus diesem kleinen Hof als den Durchgang, durch den er gekommen war. Die Schritte wurden lauter und lauter, er sah eine dunkle Gestalt um die Ecke biegen. Fieberhaft irrten seine Augen durch die nächtliche Dunkelheit und suchten einen Ausweg. War jetzt wirklich alles vorbei, waren alle Mühe und alle Vorbereitungen umsonst? Er presste sich ganz eng an die Wand hinter ihm und hoffte, der Verfolger würde ihn übersehen, als plötzlich neben ihm mit kaum wahrnehmbarem Quietschen eine Tür im nächtlichen Wind hin und her schwang. Könnte dieses der flehentlich herbeigesehnte Ausweg aus seinem Dilemma sein? Langsam bewegte er sich auf die offene Tür zu, immer dicht an die Mauer gepresst. Würde diese Tür seine Rettung werden?</text:p><text:p text:style-name="Standard"/><text:p text:style-name="Standard"><draw:frame draw:style-name="fr2" draw:name="Rahmen2" text:anchor-type="paragraph" svg:width="2cm" draw:z-index="1"><draw:text-box fo:min-height="0.499cm"><text:p text:style-name="Frame_20_contents">Rahmen an absatz</text:p></draw:text-box></draw:frame></text:p><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"><text:soft-page-break/></text:p><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard">Noch etwas text</text:p><text:p text:style-name="Standard"><text:database-display text:table-name="Tabelle1" text:table-type="table" text:column-name="Name" text:database-name="Neue Datenbank3"><Name></text:database-display></text:p><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard"><text:bookmark text:name="jms-ende"/></text:p></office:text></office:body></office:document-content>
Dreh-Gel
**
Beiträge: 28
Registriert: Sa, 25.10.2014 16:58

Re: XML effizient analysieren

Beitrag von Dreh-Gel »

Hallo Stephan,

hast du schon einen Regulären Ausdruck probiert? Ich war schon mal etwas fitter darin. Aber hier ein Ansatz:
mit:

(<draw:frame draw:.*?/draw:frame>).*?<text:p

durchsuchst du den Text. Im ersten Match und darin im ersten Submatch sollte der Bereich B sein. Den speicherst du dann zwischen und durchsuchst ihn erneut mit

<draw:frame draw:.*?/draw:frame>

Das sollten dann (hoffentlich) die gesuchten Draws sein.
Win7, AOO 4.1.1
Axel Richter
****
Beiträge: 159
Registriert: So, 17.10.2010 16:54

Re: XML effizient analysieren

Beitrag von Axel Richter »

Hallo Stephan,

ich weiß zwar nicht, was Du da genau vor hast und warum das nicht in der *.odt Datei direkt gehen soll, aber OpenOffice muss ja fast zwangsweise XML parsen können, da seine Dateien ja XML Dateien sind. Somit existieren natürlich entsprechende Services und Interfaces:

https://www.openoffice.org/api/docs/com ... ilder.html
https://www.openoffice.org/api/docs/com ... ilder.html

Nach dem Parsen steht ein DOMDocument zur Verfügung:
https://www.openoffice.org/api/docs/com ... ument.html
Dieses hat Nodes:
https://www.openoffice.org/api/docs/com ... XNode.html

Diese können natürlich auch mit entsprechenden Programmiersprachen benutzt werden.

Beispiel mit Starbasic:

Code: Alles auswählen

Sub Main

 sURI = "file:///home/axel/content.xml"
 oDocumentBuilder = createUnoService("com.sun.star.xml.dom.DocumentBuilder")
 oDOMDocument = oDocumentBuilder.parseURI(sURI)

 oBody = oDOMDocument.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", "body").item(0)
 oText = oBody.getElementsByTagNameNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", "text").item(0)
 oTextChilds = oText.getChildNodes()
  
 for i = 0 to oTextChilds.getLength()
  oTextChild = oTextChilds.item(i)
  if oTextChild.getPrefix()="draw" and oTextChild.getLocalName()="frame" then
   xray oTextChild
  end if
  if oTextChild.getPrefix()="text" and oTextChild.getLocalName()="p" then exit for
 next

End Sub
viele Grüße

Axel
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: XML effizient analysieren

Beitrag von Stephan »

hast du schon einen Regulären Ausdruck probiert?
Ich habe an diese Möglichkeit gedacht aber es trotzdem nicht getan. Ich muss nochmal nachdenken ob mir dieses Vorgehen vielleicht doch gefallen könnte.


Gruß
Stephan
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: XML effizient analysieren

Beitrag von Stephan »

ich weiß zwar nicht, was Du da genau vor hast


ich will sehr große Dokumente ändern/erweitern und wenn ich das auf odt-'Basis' mache ist das faktisch immer dadurch verlangsamt das OO die Dokumente bei Änderungen neu rendert, was ich in der GUI noch unterdrücken kann aber spätestens beim Speichern nicht mehr.

Ich schaue mir Deine HInweise noch genauer an, Diese gehen in die Richtung die ich wollte, mit der ich bisher nur nicht zurechtkam.


Gruß
Stephan
Dreh-Gel
**
Beiträge: 28
Registriert: Sa, 25.10.2014 16:58

Re: XML effizient analysieren

Beitrag von Dreh-Gel »

Stephan hat geschrieben: Ich muss nochmal nachdenken ob mir dieses Vorgehen vielleicht doch gefallen könnte.


Gruß
Stephan
Hallo Stephan,

unter Windows?
ich habe ein paar Dinge mit Regulären Ausdrücken mit VBS - Windows probiert. Auch die anderen Funktionen mit entzippen, usw. könnte man scripten - Auch wenn VBS/HTA ein bisschen angestaubt ist, aber es sollte schnell genug sein. Nur Lookbehind geht in VBS nicht, sollte aber verschmerzbar sein. RegEx in Open Office hab ich noch nicht ausprobiert, auch nicht unter Dotnet. Aber zumindest unter Dotnet sollte alles gehen. Dort sind auch schwerere Geschütze möglich (ParserGenerator).

Gruss
DG
Win7, AOO 4.1.1
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: XML effizient analysieren

Beitrag von Stephan »

hast du schon einen Regulären Ausdruck probiert? Ich war schon mal etwas fitter darin. Aber hier ein Ansatz:
mit: [...]
ich habe jetzt beide reguläre Ausdrücke ausprobiert und beidfe funktionieren nicht wie gewünscht.

Der erste Ausdruck funktioniert dann eingeschränkt wenn ich verwende:

(<draw:frame draw:.*?/draw:frame><text:p)

was aber im praktischen Gebrauch viel zu unzuverlässig wäre weil es vorausetzt das das Ende des gesuchten Textes immer begrenzt wäre durch:

"/draw:frame><text:p"

schon ein zusätzliches Leerzeichen:

"/draw:frame> <text:p"

führt zum Versagen des regulären Ausdrucks.

Außerdem ist es ja das eigentliche Ziel im ersten Schritt den Textabschnitt zu finden der begrenzt ist durch vorne das erstmalige Auftreten von "<draw:frame" und hinten durch das erstmalige Auftreten von "<text:p" außerhalb eines Tags <draw:frame [...]> [...] </draw:frame>.


Wer kann mir bei den regulären Suchausdrücken helfen?



Gruß
Stephan
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: XML effizient analysieren

Beitrag von Stephan »

unter Windows?


nein, leider unter beliebigen Betriebssystem
ich habe ein paar Dinge mit Regulären Ausdrücken mit VBS - Windows probiert. Auch die anderen Funktionen mit entzippen, usw. könnte man scripten - Auch wenn VBS/HTA ein bisschen angestaubt ist, aber es sollte schnell genug sein. Nur Lookbehind geht in VBS nicht, sollte aber verschmerzbar sein. RegEx in Open Office hab ich noch nicht ausprobiert, auch nicht unter Dotnet. Aber zumindest unter Dotnet sollte alles gehen. Dort sind auch schwerere Geschütze möglich (ParserGenerator).
ich sehe keinen Grund hier auf VBS oder andere Script-/Programmiersprachen zurückzugreifen, denn das Ganze funktioniert auch mit Basic und da die eigentliche Suche ja über vorgegebene API-Routinen erfolgt ist das an dieser Stelle mutmaßlich auch nicht zu langsam.

Das ich hingegen Basic nutzen will ist nur der Tatsache geschuldet das es die einzige Programmiersprache ist die ich selbst unter OpenOffice direkt anwenden kann. Prinzipiell spräche nichts gegen Python, Java, C++ & Co. nur kann ich selbst damit nicht umgehen und was ich hier im Thread frage ist ja nur ein Teil der Gesamtaufgabe d.h. auch eine Komplettlösung für dieses Teilproblem müsste ja dann weiter verarbeitet werden, was ich nur in Basic kann.


Gruß
Stephan
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: XML effizient analysieren

Beitrag von balu »

Hallo Stephan,

ein sehr interessantes Problem das Du da hast. Mal schaun ob ich dir auf meine Art und Weise behilflich sein kann.

Es ist eigentlich schade das Du keine Beispieldatei angehängt hast, aber auch so lässt sich damit arbeiten.

Der gepostete xml Inhalt ist so natürlich extrem schwer zu lesen. Also habe ich eine Blanko odt erstellt, entzippt, die content.xml durch deine Passage ersetzt, gespeichert, gezippt und dann in OOo 3.2.1 angeschaut. Dadurch bekam ich ein besseres Verständnis um was es geht, da ich jetzt ein Textdokument vor mir hatte.

Aber da fiel mir wieder ein, das dein xml Inhalt irgendwie komisch aussah. Also in den Optionen (Laden/Speichern Allgemein) nachgeschaut, und die Option "ODF Format auf Größe optimieren" das Häkchen rausgenommen. Danach gespeichert und dann das übliche entzippen und dann die content.xml mir noch mal angeschaut.

Für das anschauen solcher Dateien nehme ich immer wieder sehr gerne den Notepad++, allein schon wegen dem Syntax-Highlighting. Und auf einmal sah der Inhalt schon bedeutend besser aus, war viel leichter zu lesen. Doch ganz zufrieden war ich immer noch nicht, es fehlte eine Kleinigkeit. Und richtig! Es fehlte die Anzeige von Steuerzeichen, wie z.B. Zeilenumbruch (LF). Also diese Anzeige aktiviert, und "Taraaa!", schon besser. Und mit eingeschaltetem "Automatischem Zeilenumbruch" im Notepad++ war ich nun enlich zufrieden. :)

Hier jetzt mal ein Screenshot vom Notepad++
xml-screenshot_0.png
xml-screenshot_0.png (89.12 KiB) 7488 mal betrachtet
was aber im praktischen Gebrauch viel zu unzuverlässig wäre weil es vorausetzt das das Ende des gesuchten Textes immer begrenzt wäre durch:

"/draw:frame><text:p"

schon ein zusätzliches Leerzeichen:

"/draw:frame> <text:p"

führt zum Versagen des regulären Ausdrucks.
Teilweise hast Du recht, aber teilweise hast Du auch unrecht.
Denn das ende vom Draw-Frame endet wohl immer mit "/draw:frame>", aber nicht immer folgt ein "<text:p". Es kann ja auch sofort ein neues Draw-Frame folgen, wie es im aktuellen der Fall ist "</draw:frame><draw:frame". Also da hast Du recht.

Aber ob das ein Leerzeichen ist, bezweifle ich jetzt doch mal im aktuellen Falle. Denn wie auf dem Screenshot (hoffentlich) zu sehen ist, ist das kein Leerzeichen sondern ein Zeilenumbruch.
Da habe ich eben gesehen, das es doch noch die Kombination "</draw:frame></text:p>" und zwar in einer Zeile gibt. Leider nicht auf dem Screenshot zu sehen.

Wie auch immer. Ich glaube eigentlich fest daran, das dieser Zeilenumbruch die Suche mittels reguläre Ausdrücke stört, irretiert.


Noch mal meine Beobachtung eindeutig zusammengefasst.
  • Ein Draw-Frame beginnt immer mit "<draw:frame>" und endet immer mit "</draw:frame>".
  • Auf das Ende eines Draw-Frame folgt mal ein weiteres Draw-Frame "</draw:frame><draw:frame", und zwar in der gleichen Zeile.
  • Oder auf das Ende eines Draw-Frame "</draw:frame>" folgt ein Zeilenumbruch mit anschließendem "<text:p>".
  • Oder aber auf das Ende eines Draw-Frame "</draw:frame>" folgt unmittelbar ein "<text:p>"
  • Und ergänzend:
  • Das Ende einer Draw-Frame Zeile endet entweder mit "draw:z-index="0">" plus Zeilenumbruch.
  • Oder es endet mit "draw:z-index="2"><draw:image/>" plus anschließendem Zeilenumbruch.
Daraus folgt dann, das ich aus dieser deiner Aussage nicht wirklich schlau werde:
In "Abschnitt B" müssen alle "<draw:frame [...]> [...] </draw:frame>" gefunden und zur weiteren Bearbeitung zwischengespeichert werden.
Der Beginn von "Abschnitt B" ist begrenzt durch das erste Auftauchen von "<draw:frame [...]>" und das Ende ist unmittelbar vor dem ersten Aufttauchen von "<text:p [...]>" (auf gleicher Hirarchieebene wie "<draw:frame [...]>").
Denn was willst Du nun wirklich genau?
  • Willst Du alle Draw-Frames?
  • Oder willst Du nur die Draw-Frames die vor einem "<text:p [...]>" stehen, egal ob mit vorherigem Zeilenumbruch oder ohne?
Ist alles ein wenig irretierend, so das ich jetzt selbst den Überblick verloren habe. :roll:
Aber vielleicht solltest Du deine Suchstrategie irgendwie überdenken, und zwar so, das auch Zeilenumbrüche mit berücksichtigt werden.

Vielleicht konnte ich dir eine andere Sicht auf die Lage verschaffen.



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Dreh-Gel
**
Beiträge: 28
Registriert: Sa, 25.10.2014 16:58

Re: XML effizient analysieren

Beitrag von Dreh-Gel »

Stephan hat geschrieben: ich habe jetzt beide reguläre Ausdrücke ausprobiert und beide funktionieren nicht wie gewünscht.

Der erste Ausdruck funktioniert dann eingeschränkt wenn ich verwende:
(<draw:frame draw:.*?/draw:frame><text:p)

was aber im praktischen Gebrauch viel zu unzuverlässig wäre weil es vorausetzt das das Ende des gesuchten Textes immer begrenzt wäre durch:
"/draw:frame><text:p"
schon ein zusätzliches Leerzeichen:
"/draw:frame> <text:p"
führt zum Versagen des regulären Ausdrucks.
Du hast recht. Das ist eines der Probleme bei der Lösung mit Regulären Ausdrücken. Wenn da ein Leerzeichen sein darf, dann muss das auch im RegEx berücksichtigt sein. [ ]* bedeutet Null oder mehrere Leerzeichen. \s ist ein Whitespace, also auch Zeilenumbruch oder Tab. Das könnte man mit \s* berücksichtigen. Die Frage ist, welche Konstrukte vorkommen können. Solange es nur Leerzeichen oder Wortgrenzen sind, lassen sich recht einfach berücksichtigen.

(<draw:frame draw:.*?/draw:frame>\s*<text:p)

Schwieriger würde es, falls doch irgend ein <text:p innerhalb von Abschnitt B vorkommen könnte.
Stephan hat geschrieben: Außerdem ist es ja das eigentliche Ziel im ersten Schritt den Textabschnitt zu finden der begrenzt ist durch vorne das erstmalige Auftreten von "<draw:frame" und hinten durch das erstmalige Auftreten von "<text:p" außerhalb eines Tags <draw:frame [...]> [...] </draw:frame>.

Wer kann mir bei den regulären Suchausdrücken helfen?

Gruß
Stephan
Oh, AUßERHALB eines Draw-Frames. Das heißt, der RegEx müsste erkennen, ob er sich innerhalb eines Draw-befindet. Das geht an die obere Grenze dessen, was ein RegEx leisten kann. Man kann das zb. machen, in dem man alle Draw-Frames findet (und deren Start-und Endposition) und anschließend alle Text-Frames und deren Start-und Endposition. Das war jetzt mein erster Schuss und bestimmt gehts auch noch einfacher. Wichtig wäre es natürlich noch zu wissen, ob nicht noch weitere Bedingungen für das Ende von Abschnitt B ergeben. Außerdem könnte es ja sein, dass man innerhalb des Dokuments dafür sorgen könnte, dass etwas hineingeschrieben wird, mit dem man das Ende von Abschnitt B erkennen kann. Zb. als letztes ein Objekt mit einem bestimmten Namen. Das würde die Sache wieder leichter machen.

Sollte das nicht der Fall sein, dann müsste man um die RegExe was programmieren. Klar ist das portierbar, aber eine 1:1 Kopie wird nur dann gehen, wenns Open Office ist UND Open Office die RegExe ausreichend unterstützt.

Ich selbst hab mir ein paar Testfunktionen geschrieben, mit denen ich mir RegExen rumspielen kann und ein Formular zum leichten Ändern und natürlich muss man auf eine Datei zugreifen können, die man einliest usw. Dann kann man in dem RegEx durch Klammern innerhalb eines Matches ein Submatch bekommen. Zb. finde <draw ... bis /draw> und gib mir den Ihnalt, also ohne die Draw-Tags. Das ist syntaktisch bei verschiedenen Sprachen etwas unterschiedlich.

Ich kann dir mit Regulären Ausdrücken helfen.
Die Programmiersprache macht schon was aus,
Ob RegEx eine schöne Lösung ist und wie viel Aufwand es ist, hängt von deinen Dokumenten ab ...

Edit: hab noch eine Testdatei hinzugefügt, die einen regulären Ausdruck über das Dokument laufen lässt. Schön isses noch nicht, aber kann ja noch werden.
Dateianhänge
xmltest.odt
(27.77 KiB) 144-mal heruntergeladen
Win7, AOO 4.1.1
Karolus
********
Beiträge: 7431
Registriert: Mo, 02.01.2006 19:48

Re: XML effizient analysieren

Beitrag von Karolus »

Hallo

Du suchst nach den`text:p` tags die unmittelbar auf `draw.frame` tags folgen die wiederum an der Seite verankert sind?
Richtig? - oder war das andersrum.

Egal, ich hab mich mal mit schwierigem Stoff aus `lxml` befasst, dabei ist jetzt erstmal dieser Entwurf entstanden:

Code: Alles auswählen

from lxml import etree

f = etree.parse("stephan.xml")
root = f.getroot()
ns = root.nsmap

drawnodes = root.findall(".//draw:frame", ns)
ptextnodes = root.findall(".//text:p", ns)
out = []
for elem in drawnodes:
    if elem.get('{%s}anchor-type'%ns['text']) == 'page':
        nexxt = elem.getnext()
        out.append(nexxt)
        
schnittmenge = list(set(ptextnodes) & set(out))
for textnode in schnittmenge:
    print(textnode.values()) 
@Stephan: egal was du jetzt eigentlich machen willst, versuch es nicht per RegEx und wenns unbedingt BASIC sein muss dann folge den Vorschlägen von Axel Richter
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: XML effizient analysieren

Beitrag von Stephan »

Es ist eigentlich schade das Du keine Beispieldatei angehängt hast, aber auch so lässt sich damit arbeiten.
eigentlich habe ich eine Beispieldatei, denn die 'zitierte' Datei kann ja doppelt genuztzt werden, speichere sie ab und Du hast eine Beispieldatei. (Das war auch Sinn der Sache um mir zu ersparen einmal die DAtei sichtbar zu 'zitieren' damit sie meine Aussage illustriert und sie zweitens in Kopie beizufügen das man damit arbeiten kann.)
Aber ob das ein Leerzeichen ist, bezweifle ich jetzt doch mal im aktuellen Falle.
Im aktuellen Falle folgt sichtbar kein Leerzeichen, aber das muss nicht in allen Fällen so sein. Sorry, nur ich weiß auch nicht wie ich mich verhalten soll um ein Problem welches generell zu sehen ist bestmöglich zu verdeutlichen, ich habe eine Beispieldatei zur Ansicht beigefügt damit das Ganze leichter verständlich ist, ABER die Beispieldatei beschreibt nur einen konkreten Fall und nicht alle möglicherweise vorkommenden Fälle.
• Ein Draw-Frame beginnt immer mit "<draw:frame>" und endet immer mit "</draw:frame>".
ja
• Auf das Ende eines Draw-Frame folgt mal ein weiteres Draw-Frame "</draw:frame><draw:frame", und zwar in der gleichen Zeile.
nein, weil eine Zeile irgendwann voll ist und der Draw-Frame dann nicht in derselben Zeile sein kann, außerdem beschreibst Du dass Verhalten von OpenOffice/LibreOffice, das jedoch ist nicht zwingende Vorrausetzung sondern die Formatdefinition

Letztere aussage hört sich spitzfindig an, ist es aber nicht. Ich selbst hatte diesbezüglich mit den Programmieren von OOo einmal eine diskussion weil ich bemerkte das bei exakt gleichen DAteien die content.xml leicht verschieden aussehen können und die Aussage der Entwickler dazu war eindeutig, nämlich das es kein Fehler ist solange es nicht gegen die Formatdefinition verstösst.
z.B.
wenn ich in eine, ansonsten gleiche, content.xml eine leere Zeile einfüge (also auf XML-Ebene leer, nicht die XML-DEfinition für die Anzeige einer solchen ZEile bzw. Absatz im Dokument) dann ist das xml verändert ohne das sich die Darstellung des Dokuments ändert.
• Oder auf das Ende eines Draw-Frame "</draw:frame>" folgt ein Zeilenumbruch mit anschließendem "<text:p>".
• Oder aber auf das Ende eines Draw-Frame "</draw:frame>" folgt unmittelbar ein "<text:p>"
ja, aber das sind nicht alle denkbaren Fälle
• Und ergänzend:
• Das Ende einer Draw-Frame Zeile endet entweder mit "draw:z-index="0">" plus Zeilenumbruch.
• Oder es endet mit "draw:z-index="2"><draw:image/>" plus anschließendem Zeilenumbruch.
Nein. Denn das sind nur die zufällig in der Beispieldatei auftretenden Fälle.
Denn was willst Du nun wirklich genau?
Es kann in einem Dokument viele Draw-Frame-Abschnitte geben, ich suche jedoch nur diejenigen Abschnitte die sich vor dem Teil des XML befinden, welcher den Fliesstextinhalt des Dokuments kodiert, also nur die Draw-Frame-Abschnitte die statisch verankerte Objekte beschreiben (=Verankerung "An der Seite").

(Ich suche also NICHT die Draw-Frame-Abschnitte die Objekte mit Verasnkerung "Am Zeichen", "Als Zeichen" und "Am Absatz" und ggf. "Am Rahmen" beschreiben)

Deine 'Verwirrung' entsteht wo daraus das Du bisher nicht verstandedn hast das meine verbale Defnition (die die Du zitiert hast) deshalb so ist wie sie ist weil es auch innerhalb der Draw-Frame-Abschnitte den <text:p-Tag geben kannn, aber dieser Tag nicht gemeint ist.

z.B. genügt das Folgende der Definition '"<text:p" folgt auf "</draw:frame>"', aber trotzdem ist es NICHT das was ich suche weil hierbei "<text:p" gleichzeitig innerhalb eines Draw-frame-Abschnitts ist:

<draw:frame [...] <draw:frame [...] </draw:frame><text:p> [...] </text:p> [...] </draw:frame>



Gruß
Stephan
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: XML effizient analysieren

Beitrag von Stephan »

@Dreh-Gel

Deine Aussagen öffnen mir die Augen das es mit Reg-Ex ganicht bzw. nur sehr sehr kompliziert geht (bisher war ich der Meinung es ginge relativ leicht, meine Gründe Reg-Ex eher nicht zu wollen waren Andere)


nochmals zur Erklärung, das RegEx müsste (im ersten Schritt) folgenden (hier allgemein codiert/beschrieben) Abschnitt finden (rot markiert):

<draw:frame [...] </draw:frame> [...] <draw:frame [...] </draw:frame> [...] <text:p> [...] </text:p>

dürfte aber NICHT Folgenden finden (die Rotmarkierung betrifft hier nur das was man wohl FÄLSCHLICH als zu finden ansieht):

<draw:frame [...] <draw:frame [...] </draw:frame><text:p> [...] </text:p> [...] </draw:frame>


Gruß
Stephan
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: XML effizient analysieren

Beitrag von Stephan »

Du suchst nach den`text:p` tags die unmittelbar auf `draw.frame` tags folgen die wiederum an der Seite verankert sind?
jein. Ich suche die draw.frame die "An der Seite" verankert sind und text:p ist nur das Unterscheidungskriterium dafür das ich diejenigen draw.frame habe die ich will.

Falls Du also ein anderes Kriterium kennst wie sich in einer Content.xml eindeutig die "An der Seite" verankerten draw-frame (und NUR diese) identifizieren lassen wäre das prima.
@Stephan: egal was du jetzt eigentlich machen willst, versuch es nicht per RegEx und wenns unbedingt BASIC sein muss dann folge den Vorschlägen von Axel Richter
So ist auch mein Gefühl, ich bin nur damit bisher nicht weitergekommen, denn ich schaffe es bisher nur durch die Nodes zu 'interieren' kriege aber nicht den 'Text innerhalb der Nodes'.

Was ich brauche ist eine Lösung um die einzelnenen zutreffenden draw-frame-Abschnitte zunächst in eine Variable zu kriegen, z.B. also:

<draw:frame draw:style-name="fr3" draw:name="Grafik1" text:anchor-type="page" text:anchor-page-number="1" svg:x="12.966cm" svg:y="3.625cm" svg:width="1.789cm" svg:height="1.143cm" draw:z-index="2"><draw:image xlink:href="Pictures/10000000000004000000030010393590.jpg" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/></draw:frame>

(die Teile "<draw:frame" und "</draw:frame>" können auch entfallen denn ich weiß ja das sie da sind)


Oder etwas erweitert damit Du es besser verstehst (diese Erweiterung ist aber nicht Teil meiner ursprünglichen Frage):

Ich will in allen draw-frame-Abschniten die meinen Kriterien entsprechen die Tags draw:z-index ändern, so das alle draw:z-index-Tags 'gegeneinander konsistent' sind.

Verbal beschrieben:
öffne ein odt-Dokument das einen an der Seite verankerten Rahmen enthält in OpenOffice, wähle nun Einfpügen-Datei (imm menü) und wähle die Datzei die schon geöffnet ist.
Nun wird der Inhalt der Datei nochmal an die offene datei gehängt, aber die Rahmen liegen übereinander. WEnn man nun die Datei speichert und in der content.xml die Tags draw:z-index und page-number bearbeitet kann man die Rahmen in die 'richtige' Position bringen. (richtige in '', weil es hier kein richtig und falsch gibt sondern richtig nur die irrige menschliche Erwartung meint das Fliesstexte sich verhalten sollen wie DTP-Texte)


Oder die faktische Gesamtaufgabe (nicht alles aber 99% davon):
wie mache ich aus den content.xml mehrerer odt-Dokumente eine content.xml die zu einer Darstellung des Gesamtdokumentes führt als würden die aneinandergereihten Teildokumente am Bildschirm so aussehen als verhielten sie sich als DTP-Dokumente, d.h. absolut verankerte Elemente werden an den nun quasi neuen, richtigen Positionen dargestellt.

(Das Ganze darf deshalb nicht auf 'odt-Ebene' stattfinden sondern muss auf 'content.xml-Ebene' getan werden weil auf odt-Ebene letztlich das Rendern des Dokuments nicht völlig zu unterdrücken ist und das bei vielen (hundert, tausend) aneinanderzureihenden Dokumenten zuviel Zeit braucht.
Möglicherweise ist das mit dem Rendern allein ungenau beschrieben dann sei gesagt das sich OO/LO einfach nicht mehr verlässlich stabil verhalten, weil das Ganze unter Praxisbedingungen funktionieren muss und es nicht reicht wenn das bei einer gerade frisch geöffneten soffice-Sitzung gerade so noch stabil läuft.)




Gruß
Stephan
Karolus
********
Beiträge: 7431
Registriert: Mo, 02.01.2006 19:48

Re: XML effizient analysieren

Beitrag von Karolus »

Hallo
Falls Du also ein anderes Kriterium kennst wie sich in einer Content.xml eindeutig die "An der Seite" verankerten draw-frame (und NUR diese) identifizieren lassen wäre das prima.
Ja das steht doch im node:... text:anchor-type="page"

im Beispielscode oben frage ich diese Eigenschaft ab mit der Zeile:

Code: Alles auswählen

...
    if elem.get('{%s}anchor-type'%ns['text']) == 'page':
        ...
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Antworten