Announcement

Collapse
No announcement yet.

newbie xslt hilfe

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

  • newbie xslt hilfe

    Hallo Forum,
    habe eine xml-basierte Datei die in eine andere Struktur umgeformt und gefiltert werden soll. Ansich ein Fall für xslt - leider bin ich mit xml und xslt noch nicht vertraut genug,d ass es mir gelingen mag.
    Folgende Bsp-xml soll umgewandelt werden:

    Code:
    <?xml version='1.0' encoding='UTF-8'?>
    <test>
    	<point id="1" a="11" b="111">
    		<tag k="name" v="a"/>
    		<tag k="name2" v="a2"/>
    	</point>
    	<point id="2" a="22" b="222">
    		<tag k="name" v="b"/>
    		<tag k="adr" v="fun"/>
    	</point>
    	<point id="3" a="33" b="333"/>
    	<point id="4" a="44" b="444"/>
    	<point id="5" a="55" b="555"/>
    	<point id="6" a="66" b="666"/>
    	
    	<line id="1" A="1111" B="11111">
    		<pt ref="1"/>
    		<pt ref="2"/>
    		<pt ref="3"/>
    		<tag k="rest" v="5"/>
    		<tag k="abx" v="finish"/>
    	</line>
    	<line id="2" A="2222" B="22222">
    		<nd ref="5"/>
    		<tag k="hun" v="trips"/>
    	</line>
    	<line id="3" A="333" B="33333">
    		<nd ref="2"/>
    		<nd ref="5"/>
    		<tag k="all" v="56"/>
    	</line>
    </test>
    Als Resultat der Umformung möchte ich eine xml-Datei die
    1. alle <line/> mit 2 oder mehr <pt/> hat (das geht gut mit <xsl:if test="count(nd)&gt;=2">) UND
    2. alle <point/> die von <pt ref="#"> referenziert werden und Bedingung 1. erfüllen => und da steig ich irgendwie aus.

    Das Resultat soll also etwa so aussehen (leider hat die Originaldatei etwa 1GB!):
    Code:
    <?xml version='1.0' encoding='UTF-8'?>
    <test>
    	<point id="1" a="11" b="111">
    		<tag k="name" v="a"/>
    		<tag k="name2" v="a2"/>
    	</point>
    	<point id="2" a="22" b="222">
    		<tag k="name" v="b"/>
    		<tag k="adr" v="fun"/>
    	</point>
    	<point id="3" a="33" b="333"/>
    	<point id="5" a="55" b="555"/>
    		
    	<line id="1" A="1111" B="11111">
    		<pt ref="1"/>
    		<pt ref="2"/>
    		<pt ref="3"/>
    		<tag k="rest" v="5"/>
    		<tag k="abx" v="finish"/>
    	</line>
    	<line id="3" A="333" B="33333">
    		<nd ref="2"/>
    		<nd ref="5"/>
    		<tag k="all" v="56"/>
    	</line>
    </test>
    => <line id="2"> ist rausgeflogen, da zu wenig <pt/>
    => <point id="4 und 6"> sind rausgeflogen, da nicht mehr referenziert

    Irgendwelche Hinweise?

  • #2
    Hallo crash_override,

    muss es für diese Aufgabe denn XSLT sein? Mit dem XmlDocument wäre die Lösung technisch recht einfach:

    System.Xml.XmlDocument myXmlOutput = System.Xml.XmlDocument();
    System.Xml.XmlDocument myXmlInput = System.Xml.XmlDocument();
    System.Xml.XmlNode n;

    myXmlInput.Load("pfad zur datei");


    Dann z. B.:
    n = myXmlInput.SelectSingleNode("/Test/Line");
    ...


    Und:
    if (n.Nodes.Count >= 2)
    ...


    u.s.w. kannst du alles Relevante abchecken, und mit

    myXmlOutput.ImportNode(n);

    kannst du sogar einen kompletten Knoten aus deinem Quelldokument importieren.

    Gruss, Roland
    Roland Reiners

    Comment


    • #3
      Hm, das muss ich mir so mal durch den Kopf gehen lassen. Das eigentliche Problem ist ja, dass die points nicht als Kinder der lines geführt werden, sondern nur über ein Attribut darauf referenziert wird. Das liegt auch daran, dass es durchaus points als eigenständige Elemente geben darf/soll die nicht von lines referenziert werden. Dass das in meinem Wunschergebnis nicht der Fall ist liegt ja nur an der Filterung die ich durchführen möchte.

      Comment


      • #4
        Mit:

        foreach (System.Xml.XmlNode n in myXmlInput.ChildNodes)

        ruft du die einzelnen Knoten ab (wobei du hier entspr. der Struktur des XML-Input-Dokuments weiter verschachteln musst)
        , und mit

        foreach (System.Xml.XmlAttribute a in n.Attributes)
        {
        a.Name
        }


        die einzelnen Attribute die im Knoten stecken.
        Roland Reiners

        Comment


        • #5
          xslt lösung

          gibt's da nicht trotzdem eine xslt-basierte Lösung?

          Comment


          • #6
            Sorry - ich habe leider keine zur Hand. In XSLT bin ich selber Anfänger.
            Roland Reiners

            Comment


            • #7
              Probiere es so:
              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" version="1.0" encoding="UTF-8" indent="yes"/>
              
                <xsl:template match="point">
                  <xsl:variable name="id" select="@id"/>
                  <xsl:if test="//pt[@ref=$id] or //nd[@ref=$id]">
                    <xsl:copy-of select="."/>
                  </xsl:if>
                </xsl:template>
              
                <xsl:template match="line[count(pt)>=2 or count(nd)>=2]">
                  <xsl:copy-of select="."/>
                </xsl:template>
              
              </xsl:stylesheet>
              Zuletzt editiert von Thomas Meinike; 06.06.2008, 16:02.

              Comment


              • #8
                das ist es fast. einziges Problem: es werden alle <point> weitergeführt nicht nur die die von einer <line> mit zwei oder mehr <pt> referenziert werden: setze ich bei line[2] die ref auf pt[4]:
                Code:
                ...
                <line id="2" A="2222" B="22222">
                	<nd ref="4"/>
                	<tag k="hun" v="trips"/>
                </line>
                ...
                sollte dieser in der point-liste nicht mehr auftauchen, da er die Bedingungen "referenziert durch einen Knoten der weitergeführt wird weil er mind. 2 <pt> referenziert" nicht erfüllt ist.

                Comment


                • #9
                  Dann verwende diese Prüfbedingung im point-Template:
                  Code:
                  <xsl:if test="(//pt[@ref=$id] and count(//pt[@ref=$id]/../pt)>=2)
                    or (//nd[@ref=$id] and count(//nd[@ref=$id]/../nd)>=2)">
                    <xsl:copy-of select="."/>
                  </xsl:if>

                  Comment

                  Working...
                  X