Standardwert vs. Anpassungen

  • Standardwert vs. Anpassungen

    Hi,

    ich nutze XSLT bereits für einfache Aufgaben. Jetzt versuche ich damit eine etwas kompliziertere
    Aufgabe und scheitere kläglich. Die besten Google-Ergebnisse konnte ich bislang nicht umsetzen.
    Im Grunde möchte ich die Werte aus zwei Dateien zusammenfassen... aber mir fehlt noch der richtige Ansatz :(

    Datei: population-defaults.xml (Standardwerte)

    Quellcode

    1. <population>
    2. <user name="admin" uid="2000" gid="1000" password="geheim">
    3. <sshkey>ssh-dss b36c454c719718376e74519d472c04d9 admin@example.com</sshkey>
    4. <sshkey>ssh-dss f3aa4a596f846209f7615863221bd800 admin@example.com</sshkey>
    5. </user>
    6. <user name="manfred" uid="2001" gid="1000" password="test">
    7. <sshkey>ssh-dss 2e3a5d00d4a48290a95b9ea665b9b3b5 manfred@example.com</sshkey>
    8. </user>
    9. <user name="dieter" uid="2002" gid="1000" password="test">
    10. <sshkey>ssh-dss c47c47cc3575a865f6a579e6a86ae877 dieter@example.com</sshkey>
    11. </user>
    12. <user name="totalfalsch" password="test"/>
    13. </population>
    Alles anzeigen


    Datei: population.xml (Anpassungen)

    Quellcode

    1. <population>
    2. <user name="admin" password="extrageheim"/>
    3. <user name="manfred" password="supergeheim">
    4. <sshkey>ssh-dss 863c754e299f57759df5c15a6c5e04d8 manfred@example.com</sshkey>
    5. <sshkey>ssh-dss cde88fb9b526613899e8bc2eba55e680 manfred@dort.example.com</sshkey>
    6. </user>
    7. <user name="tina" uid="2007" gid="1000" password="totaltoll">
    8. <sshkey>ssh-dss 39b0f66d310752cd2f4204f6595a21ba tina@hier.example.com</sshkey>
    9. </user>
    10. <user name="fehlerhaft" password="gehtnicht"/>
    11. </population>
    Alles anzeigen


    Gewünschtes Ergebnis

    Quellcode

    1. <population>
    2. <user name="admin" uid="2000" gid="1000" password="extrageheim">
    3. <sshkey>ssh-dss b36c454c719718376e74519d472c04d9 admin@example.com</sshkey>
    4. <sshkey>ssh-dss f3aa4a596f846209f7615863221bd800 admin@example.com</sshkey>
    5. </user>
    6. <user name="manfred" uid="2001" gid="1000" password="supergeheim">
    7. <sshkey>ssh-dss 2e3a5d00d4a48290a95b9ea665b9b3b5 manfred@example.com</sshkey>
    8. <sshkey>ssh-dss 863c754e299f57759df5c15a6c5e04d8 manfred@example.com</sshkey>
    9. <sshkey>ssh-dss cde88fb9b526613899e8bc2eba55e680 manfred@dort.example.com</sshkey>
    10. </user>
    11. <user name="dieter" uid="2002" gid="1000" password="test">
    12. <sshkey>ssh-dss c47c47cc3575a865f6a579e6a86ae877 dieter@example.com</sshkey>
    13. </user>
    14. <user name="tina" uid="2007" gid="1000" password="totaltoll">
    15. <sshkey>ssh-dss 39b0f66d310752cd2f4204f6595a21ba tina@hier.example.com</sshkey>
    16. </user>
    17. </population>
    Alles anzeigen


    Die Regeln sind also eigentlich ganz einfach:
    • Anpassungen überschreiben Standardwerte
    • Ausnahme: sshkeys werden nur hinzugefügt, nicht überschrieben
    • die User werden anhand von "@name" unterschieden, uid usw. ist änderbar
    • jeder "user" benötigt zwingend @name, @uid, @gid und @password
    • Ausnahme: sshkeys sind optional
    • bei fehlenden Angaben wird der User ignoriert


    Ich bin für jeden Tip dankbar. Das oben verlinkte Beispiel ähnelt meiner Anfrage relativ stark,
    aber ich habe es nicht geschafft, das auf mein konkretes Beispiel anzuwenden.

    Die Ausgabe soll eigentlich eine Textdatei sein, aber zur besseren Veranschaulichung habe ich
    hier XML verwendet. Letztendlich nützt es mir nicht viel, wenn ich einfach ganze Tags kopiere,
    denn ich benötige die einzelnen Werte zur Speicherung in der Textdatei.


    Ciao
    - fraenki

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von fraenki ()

  • Ich habe weiter experimentiert... folgendes XSLT schafft es, aus beiden Dateien die User herauszufiltern,
    bei denen es Anpassungen der Standardwerte gibt... natürlich erstmal nur für einen Wert und ohne Berücksichtigung
    der Regeln ;) Sehr geholfen hat mir dieses schöne Beispiel.

    XML-Quellcode

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:output method="text"/>
    4. <!-- user must not be disabled -->
    5. <xsl:template match="user[not(@status='off')]">
    6. <xsl:variable name="UserName">
    7. <xsl:value-of select="@name"/>
    8. </xsl:variable>
    9. USER: <xsl:value-of select="$UserName"/>
    10. <!-- find customizations -->
    11. <xsl:for-each select="document('population.xml')/population/user[@name=$UserName]">
    12. <!-- compare passwords -->
    13. <xsl:choose>
    14. <!-- use custom value if available -->
    15. <xsl:when test="@password and @password!=''">
    16. custom value: <xsl:value-of select="@password"/>
    17. </xsl:when>
    18. <!-- fallback to default value -->
    19. <xsl:otherwise>
    20. default value: <xsl:value-of select="document('population-defaults.xml')/population/user[@name=$UserName]/@password"/>
    21. </xsl:otherwise>
    22. </xsl:choose>
    23. </xsl:for-each>
    24. </xsl:template>
    25. </xsl:stylesheet>
    Alles anzeigen


    Aufgerufen wird das XSLT mit der XML-Datei, welche die Standardwerte enthält (population-defaults.xml).
    Dann inkludiert sie die Datei mit den Anpassungen (population.xml)...

    Jetzt kann ich die Anpassungen erkennen und rausholen, nur fehlt mir dabei die Möglichkeit, auch die Werte
    für die "user" rauszuholen, bei denen es keine Anpassungen gibt. Hat jemand eine Idee, wie ich das schaffen
    könnte?


    Ciao
    - fraenki

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von fraenki ()

  • Also, wieder etwas Zeit gefunden, und noch einen Schritt weiter gekommen. Jetzt bekomme ich sowohl
    die Standardwerte als auch die Anpassungen. Allerdings nur für User, die es bereits in der Datei mit den
    Standardwerten (population-defaults.xml) gibt.

    XML-Quellcode

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:output method="text"/>
    4. <!-- user must not be disabled -->
    5. <xsl:template match="user[not(@status='off')]">
    6. <!-- save current username -->
    7. <xsl:variable name="UserName">
    8. <xsl:value-of select="@name"/>
    9. </xsl:variable>
    10. <!-- find customizations -->
    11. <xsl:for-each select="/population/user[@name=$UserName]">
    12. NAME: <xsl:value-of select="@name"/>
    13. <!-- compare passwords -->
    14. <xsl:choose>
    15. <!-- use custom value if available -->
    16. <xsl:when test="document('population.xml')/population/user[@name=$UserName]/@password">
    17. PASSWORD: <xsl:value-of select="document('population.xml')/population/user[@name=$UserName]/@password"/>
    18. </xsl:when>
    19. <!-- fallback to default value -->
    20. <xsl:otherwise>
    21. PASSWORD: <xsl:value-of select="@password"/>
    22. </xsl:otherwise>
    23. </xsl:choose>
    24. </xsl:for-each>
    25. </xsl:template>
    26. </xsl:stylesheet>
    Alles anzeigen


    Jetzt gibt es nur noch eine Herausforderung: wie schaffe ich es, die Werte für die User
    einzufügen, die in den Standardwerten noch nicht vorgekommen sind. Also um bei meinem
    zuerst genannten Beispiel-XML zu bleiben... es werden aktuell folgende User vollkommen
    ignoriert, was natürlich nicht Sinn der Sache ist:

    Quellcode

    1. <user name="tina" uid="2007" gid="1000" password="totaltoll">
    2. <sshkey>ssh-dss 39b0f66d310752cd2f4204f6595a21ba tina@hier.example.com</sshkey>
    3. </user>
    4. <user name="fehlerhaft" password="gehtnicht"/>


    Ideen?


    Ciao
    - fraenki
  • Ich habe endlich eine Lösung! :)

    Quellcode

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    3. <xsl:output method="text"/>
    4. <xsl:template match="/">
    5. <!-- ##### search new users ##### -->
    6. <xsl:for-each select="document('population.xml')/population/user">
    7. <xsl:choose>
    8. <xsl:when test="document('population-defaults.xml')/population/user[@name=current()/@name]">
    9. <!-- skipping this user because it was found in base population -->
    10. </xsl:when>
    11. <xsl:otherwise>
    12. found NEW user: <xsl:value-of select="@name"/>
    13. <!-- here we may do further processing for this new user -->
    14. </xsl:otherwise>
    15. </xsl:choose>
    16. </xsl:for-each>
    17. <!-- ##### process default user ##### -->
    18. <xsl:for-each select="/population/user">
    19. USER: <xsl:value-of select="@name"/>
    20. <!-- TODO: check that necessary information is present -->
    21. <xsl:choose>
    22. <!-- some values must not be empty -->
    23. <xsl:when test="not(@name) or not(@uid) or not(@gid) or not(@pwtype)">
    24. DEBUG: user config error
    25. </xsl:when>
    26. <xsl:otherwise>
    27. <!-- find customizations -->
    28. <!-- compare passwords -->
    29. <xsl:choose>
    30. <xsl:when test="document('population.xml')/population/user[@name=current()/@name]/@password">
    31. using custom password (<xsl:value-of select="document('population.xml')/population/user[@name=current()/@name]/@password"/>)
    32. </xsl:when>
    33. <xsl:otherwise>
    34. using default password (<xsl:value-of select="@password"/>)
    35. </xsl:otherwise>
    36. </xsl:choose>
    37. </xsl:otherwise>
    38. </xsl:choose>
    39. </xsl:for-each>
    40. </xsl:template>
    41. </xsl:stylesheet>
    Alles anzeigen


    Auch in diesem Beispiel beachte ich noch nicht alle Regeln, aber ich habe die Grundlage,
    um die Werte beider Dateien miteinander vergleichen zu können. Vielleicht hat ja mal
    jemand eine ähnliche Anforderung...


    Ciao
    - fraenki