XPath / XPath-Funktionen / Stringfunktionen / 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.
Auf dieser Seite:Alternativ zu xsl:analyze-string kann die Prüfung regulärer Ausdrücke 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 substring-before bzw. substring-after 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>
über =>, for-each und function:
//Ort/name => for-each( function($p) {
<wert inhalt="{$p}">{
analyze-string ( string($p), '[A-Z][a-z]' )
} </wert> } )
Interessant ist das Ergebnis: Sie erhalten die Information, welche Teile dem Pattern entsprechen und welche nicht.
<wert inhalt="Neustadt">
<fn:analyze-string-result
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<fn:match>Ne</fn:match>
<fn:non-match>ustadt</fn:non-match>
</fn:analyze-string-result>
</wert>
<wert inhalt="Darmstadt">
<fn:analyze-string-result
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<fn:match>Da</fn:match>
<fn:non-match>rmstadt</fn:non-match>
</fn:analyze-string-result>
</wert>
<wert inhalt="Kapstadt">
<fn:analyze-string-result
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<fn:match>Ka</fn:match>
<fn:non-match>pstadt</fn:non-match>
</fn:analyze-string-result>
</wert>
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() > 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 / 22. März 2020
Fragen? Anmerkungen? Tipps?
Bitte nehmen Sie Kontakt zu mir auf.
V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn
☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de