xpath < Sonstiges < Hochschule < Informatik < Vorhilfe
|
Status: |
(Frage) beantwortet | Datum: | 14:16 Mo 19.11.2007 | Autor: | Bastiane |
Aufgabe | <?xml version="1.1" encoding="UTF-8"?>
<book>
<div id="d1">
<chapter id="c1">
<section id="s11">
<para id="p111">bla bla bla (1)<kw>hello</kw>
</para>
<para id="p112">bla bla bla (2)<kw>world</kw>
</para>
</section>
<section id="s12">
<para id="p121">bla bla bla (3)</para>
<para id="p122">
<kw>foo</kw>bla bla bla (4)<kw>hello</kw>
</para>
</section>
</chapter>
<chapter id="c2">
<section id="s21" xml:lang="en">
<para id="p211">bla bla bla (5)</para>
<para id="p212">bla bla bla (6)<kw>world</kw>
</para>
</section>
<section id="s22" xml:lang="de">
<para id="p221" xml:lang="en">bla bla bla (7)<kw>world</kw>
</para>
<para id="p222">
<kw>world</kw>bla bla bla (8)<kw>world</kw>
</para>
</section>
</chapter>
</div>
<div id="d2" xml:lang="de">
<chapter id="c3">
<para>hi there</para>
<para>hi there</para>
<section id="d31">
<para id="p311" xml:lang="en">bla bla bla (9)</para>
<para id="p312" xml:lang="en">bla bla bla (10)</para>
<para id="p313">bla bla bla (11)</para>
</section>
<section id="d32" xml:lang="it">
<para id="p321">bla bla bla (12)</para>
<para id="p322" xml:lang="en">bla bla bla (13)</para>
<para id="p323" xml:lang="de">bla bla bla (14)</para>
</section>
</chapter>
</div>
</book>
f) Gib einen XPath-Ausdruck an, der alle Elemente selektiert, die entweder selbst oder in einem ancestor das Attribut xml:lang='de' haben.
g) Wenn die Sprache entlang der Unterbäume vererbt werden soll, reicht der vorherige Ausdruck noch nicht aus. Modifiziere den vorherigen Ausdruck, so dass nur das nächstliegende xml:lang -Attribut berücksichtigt wird. In folgendem Beispiel haben also nur die Elemente mit den Ids d2, c3, d31, p313 und p323 die Sprache de. |
Hallo zusammen!
Für f) habe ich es mal mit folgendem versucht:
//*[ancestor-or-self::*[@xml:lang='de']]
und auch mit
//ancestor-or-self::*[@xml:lang='de'].
Ersteres ist wohl richtig. Allerdings muss ich auch noch eine kurze Erklärung dazu schreiben, und da kann ich irgendwie die * nicht ganz erklären. Also das erste * bedeutet doch, dass ich im ganzen Dokument suche, oder? Und das "ancestor-or-self::" ist dann die Achse, das heißt, ich gucke für jedes Element, ob das Entsprechende für einen Vorfahren gilt. Warum müssen da [] hinter den *?
Und im zweiten Fall gibt er mir nur alle "übergeordneten" Elemente aus, also kein Kind, das einen ancestor hat, der das Attribut enthält, ein Kind gibt er mir nur dann aus, wenn es selbst das Attribut enthält. Warum?
Kann ich dann als Erklärung für den ersten * schreiben, dass er eben auch in Kindern von "schon gefundenen" Elementen suchen soll? Und was ist die Erklärung für den zweiten *?
Teil g) verstehe ich nicht so ganz. Bedeutet der letzte Satz, dass nach der Lösung aus f) nur die angegebenen Ids die Sprache de haben oder nach Lösung von g)? Denn wenn bei f) meine erste Version richtig ist, dann hätte da ja auch z. B. p311 die Sprache de - jedenfalls gibt er (Saxon) mir das so aus.
Sind dann meine beiden Varianten oben die Lösungen für f) und g)? Aber welche dann für welches?
Viele Grüße
Bastiane
|
|
|
|
Status: |
(Frage) beantwortet | Datum: | 01:01 Di 20.11.2007 | Autor: | Bastiane |
Hallo nochmal!
> g) Wenn die Sprache entlang der Unterbäume vererbt werden
> soll, reicht der vorherige Ausdruck noch nicht aus.
> Modifiziere den vorherigen Ausdruck, so dass nur das
> nächstliegende xml:lang -Attribut berücksichtigt wird. In
> folgendem Beispiel haben also nur die Elemente mit den Ids
> d2, c3, d31, p313 und p323 die Sprache de.
Also diese Aufgabenstellung habe ich jetzt glaube ich doch verstanden. Und zwar sollen jetzt nur noch Elemente ausgegeben werden, die entweder selbst dieses Attribut enthalten, oder ein Nachfahre davon sind, allerdings keinen "näheren" Vorfahren haben, der ein anderes Attribut besitzt. Das heißt, alle Elemente sollen die Attribute ihres nächsten Vorfahren erben (nur wenn der direkte Vorfahr kein Attribut hat, wird das vom nächsthöheren Vorfahren geerbt und so weiter).
Jetzt habe ich aber ein Problem, einen Ausdruck dafür zu schreiben. Ich hatte die Idee, zuerst einfach nach allen Elementen mit diesem Attribut zu suchen und von dort ausgehend dann alle Nachfahren auszugeben, die kein eigenes Attribut haben und aber eben auch keinen anderen Vorfahren, der ein anderes Attribut hat. Oder ich betrachte alle Elemente, die kein eigenes Attribut haben und suche dann den nächsten Vorfahren, der eins hat, und falls dieses ein "xml:lang="de"" ist, gebe ich den Knoten aus, und ansonsten nicht. Ich kenne zwar "and" und "or", weiß aber nicht, wie die Syntax davon ist, die Erklärungen dazu verstehe ich irgendwie nicht und Beispiele finde ich dazu keine , und vor allem fehlt mir ein "not". Gibt es so etwas auch? Oder wie drücke ich es aus, dass das Element selbst kein anderes Attribut haben darf? Bzw. sein Vorfahre?
Ach ja, die Funktion fn:lang() darf nicht verwendet werden. Aber selbst damit würde ich es nicht hinbekommen - weiß jemand, wie das ginge?
Viele Grüße
Bastiane
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 22:48 Di 20.11.2007 | Autor: | rainerS |
Hallo Bastiane!
> Hallo nochmal!
>
> > g) Wenn die Sprache entlang der Unterbäume vererbt werden
> > soll, reicht der vorherige Ausdruck noch nicht aus.
> > Modifiziere den vorherigen Ausdruck, so dass nur das
> > nächstliegende xml:lang -Attribut berücksichtigt wird. In
> > folgendem Beispiel haben also nur die Elemente mit den Ids
> > d2, c3, d31, p313 und p323 die Sprache de.
>
> Also diese Aufgabenstellung habe ich jetzt glaube ich doch
> verstanden. Und zwar sollen jetzt nur noch Elemente
> ausgegeben werden, die entweder selbst dieses Attribut
> enthalten, oder ein Nachfahre davon sind, allerdings keinen
> "näheren" Vorfahren haben, der ein anderes Attribut
> besitzt. Das heißt, alle Elemente sollen die Attribute
> ihres nächsten Vorfahren erben (nur wenn der direkte
> Vorfahr kein Attribut hat, wird das vom nächsthöheren
> Vorfahren geerbt und so weiter).
> Jetzt habe ich aber ein Problem, einen Ausdruck dafür zu
> schreiben.
Ja, das ist ein Problem. Ich habe auch eine Weile gegrübelt. Die Antwort ist - wie immer - ganz einfach
Der Trick ist der, dass ancestor immer eine von innen nach außen geordnete Liste vom übergeordneten Knoten auswählt.
Das heisst,
ancestor::*[@xml:lang]
liefert die Liste der übergeordneten Knoten, die ein Attribut xml:lang haben, geordnet von innen nach außen. Den innersten bekommst du dann durch Auswahl des ersten, also mit
ancestor::*[@xml:lang][1]
Dich interessieren aber nur die, bei denen der Wert des Attributs 'de' ist, das heisst
ancestor::*[@xml:lang][1][@xml:lang='de']
> Beispiele finde ich dazu keine
Schau mal hier
> und vor allem fehlt mir ein "not".
Das ist eine vordefinierte Funktion, du kannst zum Beispiel schreiben
ancestor::*[not(@xml:lang)]
für alle übergeordneten Knoten, die kein xml:lang Attribut haben.
Oder auch diesen Ausdruck:
not(@xml:lang) and ancestor::*[@xml:lang][1][@xml:lang='de']
Viele Grüße
Rainer
|
|
|
|
|
Status: |
(Antwort) fertig | Datum: | 01:57 Di 20.11.2007 | Autor: | rainerS |
Hallo Bastiane!
> Für f) habe ich es mal mit folgendem versucht:
>
> //*[ancestor-or-self::*[@xml:lang='de']]
>
> und auch mit
>
> //ancestor-or-self::*[@xml:lang='de'].
>
> Ersteres ist wohl richtig. Allerdings muss ich auch noch
> eine kurze Erklärung dazu schreiben, und da kann ich
> irgendwie die * nicht ganz erklären. Also das erste *
> bedeutet doch, dass ich im ganzen Dokument suche, oder?
Das erste //* ist abgekürzte Syntax.
// ist die Abkürzung für /descendant-or-self::node()/, wählt also alle Knoten im Dokument, * bedeutet, dass beliebige Elemente gewählt werden.
> das "ancestor-or-self::" ist dann die Achse, das heißt, ich
> gucke für jedes Element, ob das Entsprechende für einen
> Vorfahren gilt. Warum müssen da [] hinter den *?
Die eckigen Klammern bezeichnen ein Prädikat. Wenn du wieder einen LocationPath in eckigen Klammern hast, bedeutet das, dass der Ausdruck eine Liste von Knoten zurückliefert, die durch 'ancestor-or-self::*[@xml:lang='de']' ausgewählt werden.
> Und im zweiten Fall gibt er mir nur alle "übergeordneten"
> Elemente aus, also kein Kind, das einen ancestor hat, der
> das Attribut enthält, ein Kind gibt er mir nur dann aus,
> wenn es selbst das Attribut enthält. Warum?
Weil das Prädikat @xml:lang='de' auf jeden Knoten der Liste einzeln angewandt wird. ancestor-or-self::* wählt zwar immer die Liste aller übergeordneten Knoten, aber der Test geschieht für jeden einzeln. Diejenigen, für die der Test true zurückliefert, werden ausgegeben.
> Kann ich dann als Erklärung für den ersten * schreiben,
> dass er eben auch in Kindern von "schon gefundenen"
> Elementen suchen soll? Und was ist die Erklärung für den
> zweiten *?
Wegen des //* am Anfang wird zunächst von der Liste aller Elemente im Dokument ausgegangen, darüber iteriert. Der nächste Schritt wird für jedes Listenelement einzeln durchgeführt: nimm diesen Knoten (keine weitere Einschränkung des Elementnamens wegen des zweiten *), füge die Liste aller Ancestorknoten hinzu, prüfe für jedes Elemente dieser Liste das Prädikat. Wenn es wahr ist, gib den Knoten zurück.
Es passieren also zwei ineinander geschachtelte Iterationen, in der inneren wird das Attribut geprüft.
Im zweiten Fall ist das eine Abkürzung für
/descendant-or-self::node()/ancestor-or-self::*[@xml:lang='de']
Da passiert nur eine Iteration, für jeden Knoten einzeln wird das Attribut geprüft.
Viele Grüße
Rainer
|
|
|
|