Home
Über mich
Blog
Veröffentlichungen
IT-Trainings
Impressum


Codepoints

Zusammenfassung:

Die Spezialfunktionen string-to-codepoints, codepoints-to-string und codepoint-equal unterstützen die Konvertierung von Strings in Codepoints sowie den Vergleich von Zeichenketten auf Codepoint-Basis.

Codepoints

Bekanntlich ist jedem Zeichen ein eindeutiger Codepoint zugewiesen. Siehe hierzu meine Anmerkungen zum Thema Encoding. Hier einige wenige Beispiele:

0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
H H
u u
g g
o o

string-to-codepoints

Die Funktion "codepoints-to-string" konvertiert einen String in dessen Codepoints. Das XPath-Statement "//Ort[1]/Mensch[1]/vorname" beinhaltet den Textwert "Hugo", und die Funktion "string-to-codepoints" generiert daraus "72 117 103 111".

<xsl:value-of 
  select="string-to-codepoints(//Ort[1]/Mensch[1]/vorname)"/>

Wichtig ist dabei, daß das XPath-Statement maximal ein einziges Item anspricht (vgl. die Funktionen "exactly-one" und "zero-or-one". Ein "//Mensch/vorname" findet jedoch eine ganze Nodeliste, was die die beliebte Fehlermeldung "A sequence of more than one item is not allowed ... " zur Folge hat.

<xsl:value-of 
     select="string-to-codepoints(//Mensch/vorname)"/>

Fehlermeldung:

Fehlerlevel: fatal
Beschreibung: XPTY0004: A sequence of more than one item is not allowed 
as the first argument of string-to-codepoints() ("Hugo", "Helmut", ...)
Anfang: 16:0
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

codepoints-to-string

Umgekehrt transformiert der Aufruf "codepoints-to-string((72, 117, 103, 111))" (jawohl, doppelte runde Klammern!) eine Codepoint-Liste wieder in einen String.

<xsl:value-of 
     select="codepoints-to-string((72, 117, 103, 111))"/>

codepoint-equal

Die Funktion "codepoint-equal" vergleicht zwei Strings auf der Codepoint-Ebene, entsprechend der Unicode code point collation (http://www.w3.org/2005/02/xpath-functions/collation/codepoint):

<xsl:variable 
     name="v1" 
     select="string(//Ort[1]/Mensch[1]/vorname)"/>
<xsl:variable 
     name="v2" 
     select="string(//Ort[1]/Mensch[2]/vorname)"/>
<xsl:value-of 
     select="codepoint-equal($v1, $v2)"/>

"codepoint-equal" eignet sich nicht dazu, wie Sie vielleicht denken mögen, zwei Codepoint-Listen als Parameter zu übergeben und diese vergleichen zu lassen. Der folgende Aufruf generiert also die bereits bekannte Fehlermeldung "A sequence of more than one item ... ".

<xsl:variable name="v1" 
  select="string-to-codepoints(//Ort[1]/Mensch[1]/vorname)"/>
<xsl:variable name="v2" 
  select="string-to-codepoints(//Ort[1]/Mensch[2]/vorname)"/>
<xsl:value-of select="codepoint-equal($v1, $v2)"/>

Die Fehlermeldung lautet im Detail:

Fehlerlevel: fatal
Beschreibung: XPTY0004: A sequence of more than one item 
is not allowed as the first argument of codepoint-equal() (72, 117, ...)
Anfang: 15:0
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

Auch der Ansatz, die Codepoints in folgender Form zu übergeben, schlägt fehl:

<xsl:value-of 
  select="codepoint-equal((72, 117, 103, 111), (72, 101, 108, 109, 117, 116))"/>

Die Fehlermeldung lautet im Detail:

Fehlerlevel: fatal
Beschreibung: XPTY0004: Required item type of first argument of 
codepoint-equal() is xs:string; supplied value has item type xs:integer
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

Spezialsuche

Hin und wieder besteht die Notwendigkeit, in einer ganzen Anzahl diverser Dateien nach einem speziellen Codezeichen zu suchen, das zu allem Überfluß auch nicht darstellbar ist. Irgendein Programm meckert beispielsweise, es könne den Codepoint 150 beim besten Willen nicht ausstehen. Und irgendwo in den relevanten Dateien steckt dieses Zeichen. Aber wo?

Eine sehr angenehme Möglichkeit, die XSLT 2.0 zu bieten hat, ist der gleichzeitige Zugriff auf zahlreiche XML Dokumente mittels der collection-Funktion. Über base-uri() bekommen wir auch den jeweiligen Dateinamen heraus.

Die folgende Logik löst das Problem, daß sich in einer dieser XML Dateien ein nicht druckbares Unicode-Zeichen 150 eingeschlichen hat, das Probleme in der Weiterverarbeitung bereitet und deswegen gefunden werden muß.

<xsl:for-each 
  select="collection('file:///c:/path-to-files?select=*.xml;recurse=yes')">
  <xsl:variable 
       name="vfilename" 
       select="base-uri()"/>
  <erg filename="{$vfilename}">
  <xsl:for-each 
    select="/descendant-or-self::*[contains(., codepoints-to-string(150))]">    
    <ja wert="{codepoints-to-string(150)}" inhalt="{.}">
    <xsl:value-of select="string-to-codepoints(.)"/>
    </ja>
  </xsl:for-each>
  </erg>
</xsl:for-each>

Etwas einfacher ist die Sache, wenn die Datei mit dem Problem bereits bekannt ist:

 <xsl:template match="/" name="xsl:initial-template">
  <xsl:variable name="vsvgfile" select="fn:doc('C:/wg/SVG.xml')"/>
  <erg>
   <xsl:for-each 
       select="$vsvgfile/descendant-or-self::*
                        [contains(., codepoints-to-string(128))]">
    <absatz>
     <xsl:for-each select="string-to-codepoints(.)">
      <bbb zeichen="{codepoints-to-string(.)}">
       <xsl:value-of select="."/>
      </bbb>
     </xsl:for-each>
    </absatz>
   </xsl:for-each>
  </erg>
 </xsl:template>

Hilfe bietet auch die Möglichkeit, das gesuchte Zeichen zu ersetzen mit einem lesbaren Zeichen, das dann in der Ausgabe leichter gefunden werden kann.

<xsl:value-of 
     select="replace(., codepoints-to-string(128), 'Y')"/>

qrpic/codepoints-to-string.jpg

wg / 11. Oktober 2017




Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf (info10@wilfried-grupe.de).



Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

Mobil: 0151. 750 360 61 * eMail: info10@wilfried-grupe.de