Announcement

Collapse
No announcement yet.

Sortieren von Elementen nach Attributen in Unterelementen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Sortieren von Elementen nach Attributen in Unterelementen

    Guten Tag,

    ich habe mal gleich noch ein neues Problemchen. Und zwar möchte ich eine XML Datei sortieren um diese mit einer anderen zu vergleichen. Konkret geht es darum eine von einem Programm ausgegebene Datei einheitlich zu sortieren. Leider wirft das Programm bei jedem speichern alle Elemente wild durch einander. Für einen Diff innerhalb eines SVN ist das natürlich sehr unpraktisch. Daher habe ich mir eine XSL Transformation geschrieben, welche beide XML Dateien, die zu vergleichen sind, erst einmal normalisiert. Soweit funktioniert das auch ganz gut. Nur gibt es da noch ein paar Spezialfälle bei denen dieses Skript noch scheitert. Ein Beispiel:

    Die Transformation:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@*">
            <xsl:sort select="name()"/>
            <xsl:sort select="@text()"/>
          </xsl:apply-templates>
          <xsl:apply-templates select="*">
            <xsl:sort select="name()"/>
            <xsl:sort select="@*"/>
            <xsl:sort select="count(@*)"/>
            <xsl:sort select="@text()"/>
            <xsl:sort select="text()"/>
            <xsl:sort select="descendant::text()"/>
          </xsl:apply-templates>
          <xsl:if test="text() != ''">
            <xsl:value-of select="text()"/>
          </xsl:if>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    Die Eingabe:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <wurzel>
      <element_1 id="a:QualityResultItem"/>
      <element_1 id="a:aObjectType"/>
      <element_1 id="a:PropertyType"/>
      <element_1 id="a:Pose"/>
      <element_1 id="a:Pose"/>
      <element_2 id="a:Pose" id1="a"/>
      <element_2 id="a:Pose"/>
      <element_2 id="a:Pose" id1="a"/>
      <element_3 id="a:hasTaskType" domain="a:Task" range="a:TaskType" minCard="0.0" maxCard="1.0"/>
      <element_3 id="a:hasSituation" domain="a:Task" range="a:Situation" minCard="0.0" maxCard="*"/>
      <instance id="a">
        <instanceOf concept="b"/>
        <hasAttribute relation="blubb">
          <value>aText</value>
        </hasAttribute>
      </instance>
      <instance id="a">
        <instanceOf concept="a"/>
        <hasAttribute relation="blubb">
          <value>bText</value>
        </hasAttribute>
      </instance>
      <instance id="a">
        <instanceOf concept="a"/>
        <hasAttribute relation="zblubb">
          <value>aText</value>
        </hasAttribute>
      </instance>
      <instance id="a">
        <instanceOf concept="b"/>
        <hasAttribute relation="blubb">
          <value>aText</value>
        </hasAttribute>
      </instance>
    </wurzel>
    Die Ausgabe:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <wurzel>
      <element_1 id="a:aObjectType" />
      <element_1 id="a:Pose" />
      <element_1 id="a:Pose" />
      <element_1 id="a:PropertyType" />
      <element_1 id="a:QualityResultItem" />
      <element_2 id="a:Pose" />
      <element_2 id="a:Pose" id1="a" />
      <element_2 id="a:Pose" id1="a" />
      <element_3 domain="a:Task" id="a:hasSituation" maxCard="*" minCard="0.0" range="a:Situation" />
      <element_3 domain="a:Task" id="a:hasTaskType" maxCard="1.0" minCard="0.0" range="a:TaskType" />
      <instance id="a">
        <hasAttribute relation="blubb">
          <value>aText</value>
        </hasAttribute>
        <instanceOf concept="b" />
      </instance>
      <instance id="a">
        <hasAttribute relation="zblubb">
          <value>aText</value>
        </hasAttribute>
        <instanceOf concept="a" />
      </instance>
      <instance id="a">
        <hasAttribute relation="blubb">
          <value>aText</value>
        </hasAttribute>
        <instanceOf concept="b" />
      </instance>
      <instance id="a">
        <hasAttribute relation="blubb">
          <value>bText</value>
        </hasAttribute>
        <instanceOf concept="a" />
      </instance>
    </wurzel>
    Meine Frage ist jetzt, wie schaffe ich es, dass z.B. beim zweiten instance-Element auch nach dem Attribut des Unterelementes hasAttribute sortiert wird und somit wegen "zblubb" dieses instance-Element nach unten rutscht. Genauso, wenn jetzt statt "zblubb" nur "blubb" dastehen würde, dass es dann nach den instanceOf-Element-Attributen sortiert. Das Ganze muss jedoch so abstrakt gehalten werden dass das für beliebige Elemente mit beliebigen Unterelementen und beliebigen Attributen funktioniert. Ich war versucht zu schreiben
    <xsl:sort select="descendant::@text()" />
    Weil so hatte ich es geschafft dass die Texte der Unterelemente berücksichtigt werden. Doch leider liefert descendant ja keine Attribute zurück. Aber sowas in der Art bräuchte ich.

    Hat da jemand eine Idee? Vielen Dank schon mal!

    Viele Grüße,

    Florian Freitag.

  • #2
    für jeden tag eine template
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="/">
    
            <xsl:apply-templates select="wurzel/element_1">
                <xsl:sort select="@id"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="wurzel/element_2">
                <xsl:sort select="@id"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="wurzel/element_3">
                <xsl:sort select="@id"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="wurzel/instance">
                <xsl:sort select="instanceOf/@concept"/>
            </xsl:apply-templates>
    
        </xsl:template>
    
        <xsl:template match="element_1">
            <xsl:copy-of select="."/>
        </xsl:template>
        <xsl:template match="element_2">
            <xsl:copy-of select="."/>
        </xsl:template>
        <xsl:template match="element_3">
            <xsl:copy-of select="."/>
        </xsl:template>
        <xsl:template match="instance">
            <xsl:copy-of select="."/>
        </xsl:template>
    
    </xsl:stylesheet>

    Comment

    Working...
    X