4.1.9.4  Leerzeichen vor einem Inline-Element

Auch die Leerzeichen vor einem Inline-Element sind prüfenswert. Insbesondere um zu sehen, ob keines vergessen wurde. Eine naive Herangehensweise wäre bspw. ausgehend vom Inline-Element zu prüfen, ob ein Vorgänger Textknoten mit einem Leerzeichen abschliesst:

ends-with(preceding-sibling::text()[1],' ')
Plain Text

Dabei werden aber nur die Text-Vorgängerknoten in der Zeile betrachtet, etwaige Inline-Elemente werden aussen vor gelassen. D.h. der folgende Para würde nach diesem XPath Ausdruck noch als gültig erkannt, da nach dem "Hallo " ein Leerzeichen steht.

<p>Hallo <b>fetter Text</b><link>link text</link>
Plain Text

Offensichtlich fehlt aber ein Leerzeichen vor dem <link> -Element.

Um zu prüfen, ob der unmittelbare Vorgängerknoten ein Textknoten ist und ob dieser mit einem Leerzeichen abschliesst, kann man diesen XPath Ausdruck verwenden:

ends-with(preceding-sibling::node()[1][self::text()],' ')
Plain Text

Oder klarer:

preceding-sibling::node()[1][self::text()]/ends-with(.,' ')
Plain Text

Da wir aber bisher immer nur die preceding-sibling Achse betrachten, entgehen uns Leerzeichen, die in zuvor gesetzten Inline-Elementen vorkommen, bspw. hier:

<p>Hallo <b>fetter Text </b><link>link Text</link></p>
Plain Text

Deshalb müsste man eigentlich den XPath Ausdruck noch erweitern:

preceding-sibling::node()[1][self::* or self::text()]/ends-with(string(.),' ')
Plain Text

Dabei ist zu beachten, dass der string()-Cast auch noch verschachtelte Inline Strukturen flachklopfen würde.

Jetzt könnte man sich denken, dass man ja eigentlich diesen Ausruck verkürzen könnte zu:

preceding-sibling::node()[1]/ends-with(string(.),' ')
Plain Text

Dann würde aber auch die folgende Zeile erfolgreich geprüft:

<p>Hallo <b> fetter Text <i>Hallo</i></b><!-- Hallo --><link>link Text</link></p>
Plain Text

Denn der Kommentar schliesst mit einem Leerzeichen ab. Auch Kommentare und Processing Instructions sind vom Typ node() .