XPath 3.0, XPath 2.0, XPath 1.0 / XPath-Funktionen / Stringfunktionen / XPath: analyze-string

XPath: analyze-string

XPath: analyze-string

➪ Die XPath-Funktion analyze-string ist eine hervorragende Möglichkeit zur Stringanalyse mittels regulärer Ausdrücke. Sie generiert ein analyze-string-result-Element mit den Childnodes match bzw. non-match. Möglich ist so auch die Datenvalidierung von CSV-Dateien in XSLT 2.0 und XSL 3.0.

Alternativ zu kann die Prüfung auch mit XPath durchgeführt werden.

Nehmen Sie als Beispiel die XSL-Variable "vtelnr".


<xsl:variable name="vtelnr">
 <telnr>0151.750360</telnr>
 <telnr>0151/750360</telnr>
 <telnr>05532 50168</telnr>
 <telnr>++49(0)5532/50168</telnr>
 <telnr>05532.50168</telnr>
 <telnr>05532/50168</telnr>
</xsl:variable>

Die unten dargestellte Logik untersucht, ob eine Reihe von Telefonnummern einem vorgegebenen Pattern ^[0-9]+(\.|/| )[0-9]+$ entspricht. Das Pattern erzwingt als erstes und auch als letztes Zeichen eine Zahl; dazwischen kann entweder ein ".", ein "/" oder ein " " kommen. Dieses Trennzeichen wird über regex-group(1) angesteuert und mit bzw. in die Vorwahl sowie in die Anschlussnummer gesplittet.


<xsl:template match="/">
  <root>
   <xsl:for-each select="$vtelnr/telnr">
    <teln>
     <xsl:copy-of 
      select="fn:analyze-string
                 (
                   string(./text()), 
                   '^[0-9]+(\.|/| )[0-9]+$'
                 )"/>
    </teln>
   </xsl:for-each>
  </root>
</xsl:template>

Das Ergebnis:


<root>
  <teln>
    <analyze-string-result 
      xmlns="http://www.w3.org/2005/xpath-functions">
      <match>0151<group nr="1">.</group>750360</match>
    </analyze-string-result>
  </teln>
  <teln>
    <analyze-string-result 
      xmlns="http://www.w3.org/2005/xpath-functions">
      <match>0151<group nr="1">/</group>750360</match>
    </analyze-string-result>
  </teln>
  <teln>
    <analyze-string-result 
      xmlns="http://www.w3.org/2005/xpath-functions">
      <match>05532<group nr="1"> </group>50168</match>
    </analyze-string-result>
  </teln>
  <teln>
    <analyze-string-result 
      xmlns="http://www.w3.org/2005/xpath-functions">
      <non-match>++49(0)5532/50168</non-match>
    </analyze-string-result>
  </teln>
  <teln>
    <analyze-string-result 
      xmlns="http://www.w3.org/2005/xpath-functions">
      <match>05532<group nr="1">.</group>50168</match>
    </analyze-string-result>
  </teln>
  <teln>
    <analyze-string-result 
      xmlns="http://www.w3.org/2005/xpath-functions">
      <match>05532<group nr="1">/</group>50168</match>
    </analyze-string-result>
  </teln>
</root>

CSV validieren mit XSLT 3.0

Das unten dargestellte XSL-Beispiel spricht jede Zeile (natürlich wieder ohne Headerzeile) einer CSV-Datei an und prüft dieses mit xsl:analyze-string und dem dort definierten regex-Attribut. Entspricht die Zeile dem Pattern, so wird sie in einem <korrekt>-Element dargestellt, andernfalls mit einem <fehlerhaft>-Element.

Freilich akzeptiert der von mir verwendete XSL-Prozessor nicht die geschweiften Klammern "{}", die als Quantifizierer für wiederholte Aufrufe fungieren:


<xsl:variable name="csvdatei" select="'C:/wg/csv.txt'"/>    
<xsl:template name="csvvalidate">
 <xsl:element name="ERG">
  <xsl:for-each 
     select="unparsed-text-lines($csvdatei)[position() &gt; 1]">
   <xsl:variable name="pos" select="position()" />   
   <xsl:analyze-string 
     regex="^[0-9]+;[A-Z][a-z]+;[A-Z][a-z]+;[0-9]+(\.[0-9][0-9])?$" 
     select=".">
    <xsl:matching-substring>
     <korrekt zeile="{$pos}">
      <xsl:value-of select="." />
     </korrekt>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
     <fehlerhaft zeile="{$pos}">
      <xsl:value-of select="." />
     </fehlerhaft>
    </xsl:non-matching-substring>
   </xsl:analyze-string>
  </xsl:for-each>
 </xsl:element></xsl:template>

Um bewusst fehlerhafte Ergebnisse zu produzieren, habe ich mit einem modifizierten Pattern gearbeitet, das die optionalen Nachkommastellen der letzten Zahl unterbindet (".56" wäre also falsch).


^[0-9]+;[A-Z][a-z]+;[A-Z][a-z]+;[0-9]+$

"Bewaffnet" mit diesem Pattern, erhalte ich das erwartete Ergebnis:


<ERG>
  <fehlerhaft zeile="1">1;Holzflos;Hugo;234.56</fehlerhaft>
  <fehlerhaft zeile="2">4;Nixlos;Nicole;1234.56</fehlerhaft>
  <korrekt zeile="3">9;Sprachlos;Stefan;5430</korrekt>
  <fehlerhaft zeile="4">2;Sagblos;Stefan;321.45</fehlerhaft>
  <fehlerhaft zeile="5">3;Sorglos;Siggi;987.58</fehlerhaft>
  <fehlerhaft zeile="6">7;Herzlos;Heini;654.21</fehlerhaft>
  <fehlerhaft zeile="7">8;Rhodos;Rudi;333.33</fehlerhaft>
  <korrekt zeile="8">15;Kolos;Karl;456</korrekt>
  <fehlerhaft zeile="9">16;Sinnlos;Simone;876.54</fehlerhaft>
  <fehlerhaft zeile="10">17;Hirnlos;Horst;546.77</fehlerhaft>
  <fehlerhaft zeile="11">18;Wertlos;Werner;777.77</fehlerhaft>
  <korrekt zeile="12">19;Lustlos;Ludwig;357</korrekt>
  <korrekt zeile="13">5;Wasistlos;Willi;6789</korrekt>
  <korrekt zeile="14">10;Ruhelos;Rita;234</korrekt>
  <korrekt zeile="15">11;Schlaflos;Susi;321</korrekt>
  <korrekt zeile="16">12;Rielos;Lotte;456</korrekt>
  <korrekt zeile="17">6;Bodenlos;Betty;3450</korrekt>
  <korrekt zeile="18">13;Muehelos;Martin;222</korrekt>
  <korrekt zeile="19">14;Leinenlos;Liane;135</korrekt>
</ERG>

wg / 13. April 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.


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

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

www.wilfried-grupe.de/analyze_string.html