Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

XMLStarlet: Element durch Leerzeichen ersetzen

57 views
Skip to first unread message

Stephan Hennig

unread,
Feb 7, 2014, 12:19:55 PM2/7/14
to
Hi,

ich möchte sämtliches XML-Markup aus einem Textdokument[1] entfernen.
Das klappt recht erfreulich mit XMLStarlet[2]

$xml sel -t -m "/_:*" -v "." in.xml

oder alternativ

$xml sel --text -t -c "/_:*" in.xml


Zwischen den Wörtern des XML-Dokuments kann sich ein Element <lb>
befinden (ähnlich <br /> in HTML), welches bei den oben gezeigten
Konvertierungen leider rückstandslos verschwindet, wodurch in der
Textausgabe Wortzwischenraum verloren gehen kann.

w1<lb/>w2 ==> w1w2
w1<lb attr="1"></lb>w2 ==> w1w2

Gewünscht ist jedoch die Ausgabe "w1 w2". Ziel ist es also, ein
(ansonsten leeres) Element durch irgendeine Form von Whitespace zu ersetzen.

Behelfsweise kann ich das Markup vorbearbeiten und den Inhalt des
Elements <lb> in ein Leerzeichen ändern:

$xml ed -u "//lb" -v ' ' in.xml

ersetzt

w1<lb/>w2 ==> w1<lb> </lb>w2

Geht das noch schöner, so dass <lb> im Zwischenergebnis gar nicht mehr
vorhanden ist, sondern dort gleich "w1 w2" steht?

Viele Grüße,
Stephan Hennig

[1] Bei den XML-Dateien handelt es sich um Werke aus dem DTA-Kernkorpus,
<URL:http://www.deutschestextarchiv.de/download>.
[2] <URL:http://xmlstar.sourceforge.net/>

Bjoern Hoehrmann

unread,
Feb 7, 2014, 12:58:05 PM2/7/14
to
* Stephan Hennig wrote in de.comp.text.xml:
>ich möchte sämtliches XML-Markup aus einem Textdokument[1] entfernen.
>Das klappt recht erfreulich mit XMLStarlet[2]
>
> $xml sel -t -m "/_:*" -v "." in.xml
>
>oder alternativ
>
> $xml sel --text -t -c "/_:*" in.xml
>
>Zwischen den Wörtern des XML-Dokuments kann sich ein Element <lb>
>befinden (ähnlich <br /> in HTML), welches bei den oben gezeigten
>Konvertierungen leider rückstandslos verschwindet, wodurch in der
>Textausgabe Wortzwischenraum verloren gehen kann.

Die Regeln für beides lassen sich einfach in XSLT beschreiben, und ich
sehe, XMLStarlet kann auch XSLT. (Grob, text() immer ausgeben, Elemente
immer rekursiv mit apply-templates verarbeiten, output method 'text',
und dann nur ein template für 'lb' welches ' ' ausgibt).

>Behelfsweise kann ich das Markup vorbearbeiten und den Inhalt des
>Elements <lb> in ein Leerzeichen ändern:
>
> $xml ed -u "//lb" -v ' ' in.xml
>
>ersetzt
>
> w1<lb/>w2 ==> w1<lb> </lb>w2
>
>Geht das noch schöner, so dass <lb> im Zwischenergebnis gar nicht mehr
>vorhanden ist, sondern dort gleich "w1 w2" steht?

In http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.html konnte ich
nichts finden, wie man "ersetzen" kann, wenn `--update` das nicht von
sich aus macht. Einen Textknoten als Kind der `lb` Elemente anzufügen
hätte ich eher von --subnode/--append/--insert erwartet.
--
Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

Stephan Hennig

unread,
Feb 7, 2014, 1:26:48 PM2/7/14
to
Am 07.02.2014 18:58, schrieb Bjoern Hoehrmann:
> * Stephan Hennig wrote in de.comp.text.xml:
>>ich möchte sämtliches XML-Markup aus einem Textdokument[1] entfernen.
>>Das klappt recht erfreulich mit XMLStarlet[2]
>>
>> $xml sel -t -m "/_:*" -v "." in.xml
>>
>>oder alternativ
>>
>> $xml sel --text -t -c "/_:*" in.xml
>>
>>Zwischen den Wörtern des XML-Dokuments kann sich ein Element <lb>
>>befinden (ähnlich <br /> in HTML), welches bei den oben gezeigten
>>Konvertierungen leider rückstandslos verschwindet, wodurch in der
>>Textausgabe Wortzwischenraum verloren gehen kann.
>
> Die Regeln für beides lassen sich einfach in XSLT beschreiben, und ich
> sehe, XMLStarlet kann auch XSLT. (Grob, text() immer ausgeben, Elemente
> immer rekursiv mit apply-templates verarbeiten, output method 'text',
> und dann nur ein template für 'lb' welches ' ' ausgibt).

Aha? Leider sind meine Kenntnisse in XML und insbesondere XSLT ziemlich
bescheiden. XMLStarlet kann mittels des Schalters -C jedoch das
verwendete XSLT anzeigen. Wegen des vorhandenen Namensraumes und da ich
nur den Text unterhalb /TEI/text erhalten möchte, unterscheiden sich die
tatsächlich verwendeten Kommandozeilen von den oben gezeigten etwas:

> $xml sel -C -N my=http://www.tei-c.org/ns/1.0 -t -m "/my:TEI/my:text" -v "." in.xml
> <?xml version="1.0"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://www.tei-c.org/ns/1.0" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
> <xsl:output omit-xml-declaration="yes" indent="no"/>
> <xsl:template match="/">
> <xsl:for-each select="/my:TEI/my:text">
> <xsl:call-template name="value-of-template">
> <xsl:with-param name="select" select="."/>
> </xsl:call-template>
> </xsl:for-each>
> </xsl:template>
> <xsl:template name="value-of-template">
> <xsl:param name="select"/>
> <xsl:value-of select="$select"/>
> <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
> <xsl:value-of select="'&#10;'"/>
> <xsl:value-of select="."/>
> </xsl:for-each>
> </xsl:template>
> </xsl:stylesheet>

bzw.

> $xml sel -C --text -N my=http://www.tei-c.org/ns/1.0 -t -c "/my:TEI/my:text" in.xml
> <?xml version="1.0"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://www.tei-c.org/ns/1.0" version="1.0">
> <xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
> <xsl:template match="/">
> <xsl:copy-of select="/my:TEI/my:text"/>
> </xsl:template>
> </xsl:stylesheet>

Darin herumzufummeln, ist mir allerdings nicht möglich. Für einen
kleinen Patch wäre ich dankbar!

Viele Grüße,
Stephan Hennig

Bjoern Hoehrmann

unread,
Feb 8, 2014, 9:03:54 AM2/8/14
to
* Stephan Hennig wrote in de.comp.text.xml:
>Am 07.02.2014 18:58, schrieb Bjoern Hoehrmann:
>> Die Regeln für beides lassen sich einfach in XSLT beschreiben, und ich
>> sehe, XMLStarlet kann auch XSLT. (Grob, text() immer ausgeben, Elemente
>> immer rekursiv mit apply-templates verarbeiten, output method 'text',
>> und dann nur ein template für 'lb' welches ' ' ausgibt).
>
>Aha? Leider sind meine Kenntnisse in XML und insbesondere XSLT ziemlich
>bescheiden. XMLStarlet kann mittels des Schalters -C jedoch das
>verwendete XSLT anzeigen. Wegen des vorhandenen Namensraumes und da ich
>nur den Text unterhalb /TEI/text erhalten möchte, unterscheiden sich die
>tatsächlich verwendeten Kommandozeilen von den oben gezeigten etwas:

Sowas hier sollte reichen:

<xsl:transform
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
version='1.0'>

<xsl:output method='text' encoding='utf-8' />

<xsl:template match='lb'>
<xsl:text> </xsl:text>
</xsl:template>

</xsl:transform>

Für sowas wie

<x>...
<y>dfksd</y>
<z>###<lb/>###</z>
</x>

ist die Ausgabe

...
dfksd
### ###

Was den Anforderungen entspricht, soweit ich sie verstanden habe.
0 new messages