Discussion:
Mit XSLT/XPath Buchstaben aus einer Reihe auslesen
(zu alt für eine Antwort)
Andreas
2006-05-05 15:29:45 UTC
Permalink
Hallo zusammen!
kann mir jemand sagen, wie ich mit XSLT/Xpath einen Buchstaben aus
einer "Zahlenreihe" auslese?

Ich will zum Beispiel das bei "A-C"
mir A, B C ausgegeben wird.
Also das er mir einfach alle zwischen zwei Buchstaben enthaltenden
Buchstaben ausgibt.

Kann mir da jemand weiterhelfen?

Danke!
Martin Honnen
2006-05-05 15:58:25 UTC
Permalink
Post by Andreas
Ich will zum Beispiel das bei "A-C"
mir A, B C ausgegeben wird.
Also das er mir einfach alle zwischen zwei Buchstaben enthaltenden
Buchstaben ausgibt.
Mit XSLT 2.0/XPath 2.0

<xsl:value-of select="codepoints-to-string(string-to-codepoints('A') to
string-to-codepoints('H'))" />

So du als Eingabe wirklich A-C hast, dann halt z.b.

<xsl:value-of
select="codepoints-to-string(string-to-codepoints(substring('A-C', 1,
1)) to string-to-codepoints(substring('A-C', 3, 1)))" />
--
Martin Honnen
http://JavaScript.FAQTs.com/
Andreas
2006-05-06 12:54:04 UTC
Permalink
Hey!!
Das ist ja echt super!!!! :-)
Vielen Dank!!!

Also wenn du so super gut in XSLT/XPath bist, kannst du mir
dann evtl. auch sagen, Wie ich so eine Reihe nicht zuerst ausgebe,
sondern zuerst mit einer anderen Reihe vergleiche, und nur die
Buchstaben ausgebe, die in der anderen Reihe nicht vorhanden sind?

Das würde mir echt weiterhelfen!!!

Vielen Dank nochmal!!
Andreas
Martin Honnen
2006-05-06 13:42:36 UTC
Permalink
Post by Andreas
Wie ich so eine Reihe nicht zuerst ausgebe,
sondern zuerst mit einer anderen Reihe vergleiche, und nur die
Buchstaben ausgebe, die in der anderen Reihe nicht vorhanden sind?
Eventuell einfach mit der replace-Funktion, Beispiel


<xsl:variable name="seq1"
select="codepoints-to-string(string-to-codepoints('A') to
string-to-codepoints('H'))" />
<xsl:variable name="seq2"
select="codepoints-to-string(string-to-codepoints('D') to
string-to-codepoints('F'))" />
<xsl:value-of select="($seq1, $seq2, replace($seq1, $seq2, ''))"
separator="&#13;&#10;" />

ergibt

ABCDEFGH
DEF
ABCGH

Aber beachte, dass in der replace-Funktion
<http://www.saxonica.com/documentation/functions/intro/fn_replace.html>
das zweite Argument ein Pattern ist, in dem gewisse Zeichen eine
Bedeutung (z.B. als Quantifier) haben.
--
Martin Honnen
http://JavaScript.FAQTs.com/
Martin Honnen
2006-05-06 13:47:18 UTC
Permalink
Post by Martin Honnen
Aber beachte, dass in der replace-Funktion
<http://www.saxonica.com/documentation/functions/intro/fn_replace.html>
das zweite Argument ein Pattern ist, in dem gewisse Zeichen eine
Bedeutung (z.B. als Quantifier) haben.
Deshalb ist die schon seit XPath 1.0 vorhandene translate-Funktion in
diesem Fall wohl sinnvoller als replace:
translate($seq1, $seq2, '')
--
Martin Honnen
http://JavaScript.FAQTs.com/
Andreas
2006-05-06 14:23:15 UTC
Permalink
Super!
Vielen vielen Dank!
Werd das gleich mal austesten... :-)

Wenn ich noch Fragen hab, hoff ich das du mir dann auch evtl.
weiterhefen kannst..

Also vielen Dank nochmal
Andreas
Andreas
2006-05-06 15:06:46 UTC
Permalink
Wie verändere ich denn das ganze, wenn ich zuerst garnicht weiß was
für eine
Buchstabenreihe ich habe?
Also das ich aus einem Document zuerst z.B. "A-F" auslese, prüfe,
welche Buchstaben ich schon in einem anderen Document vorhanden habe,
und dann den Rest, der nicht vorhanden ist, ausgebe?

Quasi so wie vorher, nur das ich
a) die Buchstabenreihe zuerst nicht kenne, und
b) die enthaltenen Buchstaben mit den Buchstaben vergleiche,
die schon in einem anderen Document vorhanden sind.

Ich weiß, das hört sich echt verwirrend an. Tut mir leid wenn ich das
evtl.
umständlich beschrieben habe...

Muss da eben so ne Arbeit bis Montag erledigen.
Darum bin ich auch gerade etwas nervös....

Vielen Dank
Andreas
Martin Honnen
2006-05-06 15:12:49 UTC
Permalink
Post by Andreas
Quasi so wie vorher, nur das ich
a) die Buchstabenreihe zuerst nicht kenne, und
b) die enthaltenen Buchstaben mit den Buchstaben vergleiche,
die schon in einem anderen Document vorhanden sind.
Wie sieht das genau aus, poste doch die relevanten Teile der XML-Dokumente.
--
Martin Honnen
http://JavaScript.FAQTs.com/
Andreas
2006-05-06 15:26:28 UTC
Permalink
Post by Martin Honnen
Wie sieht das genau aus, poste doch die relevanten Teile der XML-Dokumente
Also das ist das XML was geprüft werden soll:

<RegelListe>
<Regel>
<Regel1>1</Regel1>
<NummernListe>
<Nummer>1</Nummer>
<Nummer>A</Nummer>
<Nummer>F</Nummer>
</NummernListe>
</Regel>
</RegelListe>



Das ist das "Original"-XML was mir quasi als Vorlage dient.

<Liste>
<Nummer>
<data nummer="A-G"/>
<data nummer="8"/>
<data nummer="B"/>
<data nummer="3"/>
</Nummer>
</Liste>



Ich will Prüfen, ob aus der Buchstabenreihe "A-G" irgendwelche
Buchstaben in dem obigen XML schon enthalten sind.
Der Rest, der nicht enthalten ist, will ich ausgeben.

Weißt du was ich meine?
Grüße
Andreas
Andreas
2006-05-06 15:27:51 UTC
Permalink
In der Ausgabe soll (von den Buchstaben her) nur noch:
B,C,D,E,G

erscheinen
Martin Honnen
2006-05-06 17:33:19 UTC
Permalink
Post by Andreas
<RegelListe>
<Regel>
<Regel1>1</Regel1>
<NummernListe>
<Nummer>1</Nummer>
<Nummer>A</Nummer>
<Nummer>F</Nummer>
</NummernListe>
</Regel>
</RegelListe>
Nehmen wir an, obiges ist regelliste.xml,
Post by Andreas
Das ist das "Original"-XML was mir quasi als Vorlage dient.
<Liste>
<Nummer>
<data nummer="A-G"/>
<data nummer="8"/>
<data nummer="B"/>
<data nummer="3"/>
</Nummer>
</Liste>
und obiges ist das Eingabe-Dokument für das XSLT 2.0 Stylesheet, das wie
folgt aussieht:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">

<xsl:output method="text" />

<xsl:template match="/">
<xsl:variable name="data-range"
select="Liste/Nummer/data[1]/@nummer" />

<xsl:variable name="data-list"
select="for $n in
document('regelliste.xml')/RegelListe/Regel/NummernListe/Nummer return
string-to-codepoints($n)[1]" />

<xsl:variable name="codePoints"
select="string-to-codepoints(substring($data-range, 1, 1)) to
string-to-codepoints(substring($data-range, 3, 1))" />

<xsl:value-of select="codepoints-to-string($codePoints[not(. =
$data-list)])" />
</xsl:template>

</xsl:stylesheet>

dann bekomme ich mit Saxon 8.7.1 Java als Ausgabe

BCDEG
--
Martin Honnen
http://JavaScript.FAQTs.com/
Andreas
2006-05-06 17:54:27 UTC
Permalink
Du bist echt genial!!
Ich danke Dir vielmals!!!!

Du hast mir echt das Wochenende gerettet! :-)

Vielen Dank!
Schönen Abend noch!


Grüße
Andreas
Andreas
2006-05-07 12:41:15 UTC
Permalink
Komm da irgendwie nicht wirklich klar mit...
Also hier nochmal meine Aufgabe:

Es soll geprüft werden welche Buchstaben in dem "test.xml" und welche
in dem
"vorlagen.xml" vorhanden sind. Die fehlenden sollen ebenfalls
ausgegeben werden.
Das Problem ist:
- In "vorlage.xml" sind Buchstaben-Reihen enthalten (z.B. A-C) Da hast
Du mir ja den Code gegeben...
- Für jede "RegelNummer" (enthalten in "test.xml") soll diese
Auswertung separat ausgegeben werden.
Also welche Buchstaben in "RegelNummer1" nicht vorhanden sind, soll in
den "Block"RegelNummer1" der
Ausgabe enthalten sein...usw...

Kannst du mir sagen was an dem XSLT nicht stimmt?
Vielen Dank!

Grüße
Andreas


---- test.xml ----

<?xml version="1.0" encoding="ISO-8859-2"?>
<?xml-stylesheet type="text/xsl" href="transformTest.xslt"?>
<RegelListe>
<Regel>
<RegelNummer>1</RegelNummer>
<Ausschluss1>
<Nummer>1</Nummer>
<Nummer>A</Nummer>
</Ausschluss1>
<Ausschluss2>
<Nummer>41</Nummer>
<Nummer>C</Nummer>
</Ausschluss2>
</Regel>
<Regel>
<RegelNummer>2</RegelNummer>
<Ausschluss1>
<Nummer>999</Nummer>
<Nummer>55</Nummer>
</Ausschluss1>
<Ausschluss2>
<Nummer>51</Nummer>
<Nummer>52</Nummer>
</Ausschluss2>
</Regel>
</RegelListe>
---------------

---- vorlage.xml ----

<?xml version="1.0" encoding="ISO-8859-2"?>
<DanebenNicht>
<G1>
<data fehler="A"/>
<data fehler="8"/>
<data fehler="B"/>
<data fehler="3"/>
<data fehler="E-G"/>
<data fehler="C"/>
</G1>
<G2>
<data fehler="A"/>
<data fehler="8-11"/>
<data fehler="L"/>
<data fehler="3"/>
<data fehler="E-G"/>
<data fehler="C"/>
</G2>
</DanebenNicht>
----------------------


---- neuTransform.xslt ----

<?xml version="1.0" encoding="ISO-8859-2"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="2.0">
<xsl:output method="xml" version="1.0" encoding="ISO-8859-2"
indent="yes"/>

<xsl:template match="/">
<xsl:variable name="unserTest"
select="RegelListe/Regel/NummernListe/Nummer return
string-to-codepoints(Nummer[1])" />

<xsl:variable name="vorlage" select="for $n in
document('vorlage.xml')/Liste/Nummer/data[1]/@nummer return
string-to-codepoints($n)[1]" />

<xsl:variable name="vergleich"
select="string-to-codepoints(substring($unserTest, 1, 1)) to
string-to-codepoints(substring($unserTest, 3, 1))" />

<xsl:value-of select="codepoints-to-string($vergleich[not(. =
$vorlage)])" />
</xsl:template>
</xsl:stylesheet>
Andreas
2006-05-07 14:12:06 UTC
Permalink
Was ich auch nicht verstehe, was das "$n" bedeutet:

<xsl:variable name="data-list" select="for $n in
document('regelliste.xml')/RegelListe/Regel/NummernListe/Nummer
return string-to-codepoints($n)[1]" />

Ich mein das "$" bezieht sich ja immer auf eine Variable. Aber mit der
definition dieser Variablen komm ich nicht so klar...
Martin Honnen
2006-05-07 15:30:53 UTC
Permalink
Post by Andreas
<xsl:variable name="data-list" select="for $n in
document('regelliste.xml')/RegelListe/Regel/NummernListe/Nummer
return string-to-codepoints($n)[1]" />
Ich mein das "$" bezieht sich ja immer auf eine Variable. Aber mit der
definition dieser Variablen komm ich nicht so klar...
Richtig, Variablen- oder Parameternamen beginnen mit '$'.
Die Möglichkeit eines Ausdruckes der Form
for $varName
in expression1
return expression2
ist neu in XPath 2.0, das gab es so nicht in XPath 1.0.

Was

<xsl:variable name="data-list"
select="for $n in
document('regelliste.xml')/RegelListe/Regel/NummernListe/Nummer return
string-to-codepoints($n)[1]" />

machen soll, ist die Sequenz von Nummer-Elementen in dem Dokument
regelliste.xml in eine Sequenz von Codepunkten umzuwandeln, so dass dann
später der Vergleich
$codePoints[not(. = $data-list)])
erfolgen kann.
--
Martin Honnen
http://JavaScript.FAQTs.com/
Andreas
2006-05-07 15:49:45 UTC
Permalink
Super erklärt! :-)
Vielen Dank!

Andreas
Andreas
2006-05-07 17:56:04 UTC
Permalink
Also ich hab es jetzt geschafft, das alles soweit einigermaßen
funktioniert.
Problem scheint mir allerdings noch die oberen zwei Zeilen zu machen:

<xsl:variable name="data-range"
select="document('regelListe.xml')/DanebenNicht/G1/data[1]/@danebenNicht"
/>

<xsl:variable name="unserTest" select="for $n in
RegelListe/Regel/*/LeistungsNummer return
string-to-codepoints($n)[1]" />
<xsl:variable name="vergleich"
select="string-to-codepoints(substring($data-range, 1, 1)) to
string-to-codepoints(substring($data-range, 3, 1))" />

<xsl:value-of select="codepoints-to-string($vergleich[not(. =
$unserTest)])" />


Sobald ich "G1" mit einem * tauschen will, funktioniert es nicht mehr.
Ich kann das aber nicht so statisch stehen lassen, da ich auch "G2
G3..." usw.
ansprechen will.
Ebenso ist der restliche Teil ein Problem:

"G1/data[1]/@danebenNicht"

Hier wird wohl nur das erste attribut geprüft.
Ich will aber alle Prüfen.
Also:

<data danebenNicht="A-J"/>
<data danebenNicht="G-L"/>

Ich will nicht nur das es bei "A-J" alle Buchstaben prüft, sondern
auch bei "G-L".

Weißt du was ich meine?
Andreas
Andreas
2006-05-07 18:20:24 UTC
Permalink
Post by Andreas
Sobald ich "G1" mit einem * tauschen will, funktioniert es nicht mehr.
Ich kann das aber nicht so statisch stehen lassen, da ich auch "G2
G3..." usw.
ansprechen will.
Hier wird wohl nur das erste attribut geprüft.
Ich will aber alle Prüfen.
<data danebenNicht="A-J"/>
<data danebenNicht="G-L"/>
Ich will nicht nur das es bei "A-J" alle Buchstaben prüft, sondern
auch bei "G-L".
Also es liegt an den Zeilen:

<xsl:variable name="regelListe"
select="document('regelListe.xml')/DanebenNicht/G1/data[1]/@danebenNicht"
/>

und

<xsl:variable name="vergleich"
select="string-to-codepoints(substring($regelListe, 1, 1)) to
string-to-codepoints(substring($regelListe, 3, 1))" />


Es wird eine genaue angabe als variable benötigt.
Also ich kann "G1" nicht mit einem stern * ersetzen...
Ich weiß sonst einfach nicht wie ich das lösen könnte...
Andreas
2006-05-08 05:26:18 UTC
Permalink
Kann ich sowas evtl. besser realisieren, wenn ich auf ein doc zugreife,
das meine ganzen möglichen Buchstaben enthält?

<List>
<CharNr id="1">A</CharNr>
<CharNr id="2">B</CharNr>
<CharNr id="3">C</CharNr>
<CharNr id="4">D</CharNr>
<CharNr id="5">K1</CharNr>
<CharNr id="6">E</CharNr>
<CharNr id="7">F</CharNr>
<CharNr id="8">G</CharNr>
<CharNr id="9">H</CharNr>
<CharNr id="10">J</CharNr>
<CharNr id="11">K2</CharNr>
</List>


Wenn ja, wie sähe da der code aus?

Grüße
Andreas
Andreas
2006-05-08 06:25:13 UTC
Permalink
Ich löse das nun einfach mit "wenn, dann"
z.B. wenn "A-C",
dann, A,B,C.

Hab hier den code. aber irgendwo ist ein fehler drin:
Ergibt mir immer A,B,C aus. egal, ob in dem Doc nun "A-C" enthalten
ist, oder nicht...


<xsl:for-each select="$regelDoc/*[@key=$strKey]/data/@danebenNicht">
<xsl:choose>
<xsl:when test="contains(substring('A', 1, 1), substring('C', 3,
1))">
<xsl:text>A, B, C, </xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
Andreas
2006-05-08 07:04:17 UTC
Permalink
Habe es soweit.
Aber ich will, das er mir jetzt folgendes ausgibt:
"A, B, C, D"

Er gibt mir aber drei mal "A, B, C" aus.
Kannst du mir sagen warum?
was ist falsch daran?

XSLT:

<xsl:variable name="strKey" as="xs:string" select="."/>
<xsl:for-each select="$regelDoc/*[@key=$strKey]/data/@danebenNicht">
<xsl:if test="substring-before(., '-') and substring-after(., '-')">
<xsl:choose>
<xsl:when test="contains(substring('A', 1, 1), substring('C', 3,
1))">
<xsl:text>A, </xsl:text>
<xsl:text>B, </xsl:text>
<xsl:text>C </xsl:text>
</xsl:when>
<xsl:when test="contains(substring('B', 1, 1), substring('D', 3,
1))">
<xsl:text>B, </xsl:text>
<xsl:text>C, </xsl:text>
<xsl:text>D </xsl:text>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>



XML:

<G1>
<data danebenNicht="5"/>
<data danebenNicht="A-C"/>
<data danebenNicht="B-D"/>
<data danebenNicht="3"/>
<data danebenNicht="E-K"/>
<data danebenNicht="2"/>
<data danebenNicht="449"/>
<data danebenNicht="1"/>
<data danebenNicht="2328"/>
</G1>
Andreas
2006-05-08 08:18:05 UTC
Permalink
Ok, hab das ganze jetzt.
Zwar recht umständlich, aber ich habs...

Kann mir aber jemand weiterhelfen wie ich das am besten mache, dass das
Programm mir jetzt im unteren fall zum Beispiel nur A,B,C ausgibt, wenn
auch wirklich im anderen doc. A,B,C nicht vorhanden ist.
Also wenn jetzt "B" vorhanden ist, will ich nur "A" und "C" ausgegeben
haben.
Weiß jemand wie ich das machen kann?

<xsl:variable name="strKey" as="xs:string" select="."/>
<xsl:for-each select="$regelDoc/*[@key=$strKey]/data/@danebenNicht">
<xsl:if test="substring-before(., '-') and substring-after(.,
'-')">
xsl:choose>
<xsl:when test="substring(., 1, 1) = 'A' and substring(., 3, 1)
= 'C'">
<xsl:if test="not
(exists($unserDoc/Regel/*/LeistungsNummer[.=xs:string('Y')]))">
<xsl:if test="not
(exists($unserDoc/Regel/*/LeistungsNummer[.=xs:string('Z')]))">
<LeistungsNummer>A</LeistungsNummer>
<xsl:text>
</xsl:text>
<LeistungsNummer>B</LeistungsNummer>
<xsl:text>
</xsl:text>
<LeistungsNummer>C</LeistungsNummer>
</xsl:if>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>

Loading...