Announcement

Collapse
No announcement yet.

Namespace im Wurzelknoten ändern -> Problem mit Kindknoten

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

  • Namespace im Wurzelknoten ändern -> Problem mit Kindknoten

    Guten Tag,

    ich möchte mit einer XSL Transformation die Namespace-Definitionen im Wurzelknoten ändern. Dazu hatte ich hier in diesem Forum schon einmal eine Fragegestellt, wobei herauskam dass es am Besten ist einfach den Wurzelknoten neuzuschreiben. Das habe ich mittlerweile auch gemacht, doch bekomme ich dabei ein Problem. Und zwar werden die alten Namespace-Definitionen, die vorher im Wurzelknoten standen, in alle Kindknoten geschrieben. Hat jemand eine Idee wie ich das verhindern kann?

    Damit ihr euch das besser vorstellen könnt was ich meine hier noch einwenig Quellcode:

    Die XSL Transformation:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet 
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#">
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="oxml:ontology">
        <oxml:ontology
          xmlns="http://www.xpress-project.eu"
          xmlns:a="http://www.xpress-project.eu"
          xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1">
          <xsl:apply-templates select="node() | @*"/>
        </oxml:ontology>
      </xsl:template>
      
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    Das ursprüngliche XML Dokument:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    
    <!-- 
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#"  
    	should be
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1" 
    -->
    
    <oxml:ontology
    	xmlns="http://www.xpress-project.eu#"
    	xmlns:a="http://www.xpress-project.eu#"
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#">
      <oxml:axiom>
        <oxml:text language="flogic">TEXT</oxml:text>
      </oxml:axiom>
      <oxml:relation />
    </oxml:ontology>
    Das gelieferte Ergebnis der Transformation als XML Dokument:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- 
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#"  
    	should be
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1" 
    -->
    <oxml:ontology 
      xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1" 
      xmlns="http://www.xpress-project.eu" 
      xmlns:a="http://www.xpress-project.eu">
      <oxml:axiom 
        xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#" 
        xmlns="http://www.xpress-project.eu#" 
        xmlns:a="http://www.xpress-project.eu#">
        <oxml:text language="flogic">TEXT</oxml:text>
      </oxml:axiom>
      <oxml:relation 
        xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#" 
        xmlns="http://www.xpress-project.eu#" 
        xmlns:a="http://www.xpress-project.eu#" />
    </oxml:ontology>
    Das eigentlich gewünschte Ergebnis:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    
    <!-- 
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#"  
    	should be
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1" 
    -->
    
    <oxml:ontology
    	xmlns="http://www.xpress-project.eu"
    	xmlns:a="http://www.xpress-project.eu"
    	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1">
      <oxml:axiom>
        <oxml:text language="flogic">TEXT</oxml:text>
      </oxml:axiom>
      <oxml:relation />
    </oxml:ontology>
    Würde mich echt freuen wenn ihr mir bei diesem Problem weiterhelfen könntet. Ich habe schon in dem englischen Forum "bytes" eine Teil-Antwort gefunden, dass man sich ein eigenes Copy-Template nach folgendem Schema schreiben sollte, doch dabei gehen alle Namespaces verloren und ist somit leider auch keine Lösung.

    Code:
      <xsl:template match="node() | @*">
        <xsl:copy>
          <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="oxml:ontology">
        <oxml:ontology xmlns="http://www.xpress-project.eu"
                       xmlns:a="http://www.xpress-project.eu"
          xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1">
          <xsl:for-each select="*">
            <xsl:call-template name="copy"/>
          </xsl:for-each>
        </oxml:ontology>
      </xsl:template>
      
      <xsl:template name="copy">
        <xsl:element name="local-name()">
          <xsl:copy-of select="@*"/>
          <xsl:for-each select="*">
            <xsl:call-template name="copy"/>
          </xsl:for-each>
        </xsl:element>
      </xsl:template>
    Vielen Dank schon einmal im Voraus!!!!

    Florian

  • #2
    Gib exclude-result-prefixes="abc xyz" bei xsl:stylesheet an (abc, xyz usw. entsprechend anpassen).

    Comment


    • #3
      Danke, für die schnelle Antwort! Ich habe die xslt-Datei wie folgt angepasst:

      Code:
      <xsl:stylesheet 
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#"
        xmlns:a="http://www.xpress-project.eu#"
        exclude-result-prefixes="oxml a">
      Doch leider ist das Ergebnis immer noch dasselbe. Irgendwo muss ich noch einen Fehler machen, denn in einem anderen Forum habe ich auch schon gelesen, dass das so wie du meintest funktionieren muss. Leider bei mir nicht.

      Für meine XSL Transformationen verwende ich Microsoft Visual Studio 2008 (kriegt man hier im Institut auf jeden Rechner standardmäßig draufinstalliert). Könnte darin ein Problem bestehen? Eigentlich bin ich im Großen und Ganzen ganz zufrieden mit dem VS 2008.

      Gruß Florian Freitag

      Comment


      • #4
        Um ein eventuelles Probelm mit dem VS 2008 auszuschließen habe ich jetzt mal noch die Transformation mit Kernow 1.6.1, welches auf Saxon aufbaut, ausgeführt. Leider mit exakt dem selben Ergebnis.

        Gruß Florian

        Comment


        • #5
          Vereinfachteres Beispiel

          Hallo,

          da die Lösung wohl offensichtlich nicht so einfach ist, habe ich mir mal noch ein vereinfachteres Beispiel geschrieben und eine XSL Transformation die eigentlich funktionieren müsste.

          XML - Datei in der ich im Wurzelknoten die Namespace URI Dekleration von old_namespace umbenennen möchte:
          Code:
          <?xml version = '1.0' encoding = 'iso-8859-1'?>
          
          <ROOT xmlns:NAME='old_namespace'>
            <NAME:element attr1="xxx" >
              <NAME:subElement attr2="yyy">abcdefghi</NAME:subElement>
            </NAME:element>
            <NAME:element attr1="xxx" >
              <NAME:subElement attr2="yyy">abcdefghi</NAME:subElement>
            </NAME:element>
          </ROOT>
          Die XSLT - Datei die eigentlich genau das machen sollte.
          Code:
          <?xml version="1.0" encoding="iso-8859-1"?>
          
          <xsl:stylesheet version="1.0"
                          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                          xmlns:NAME="old_namespace"
                          exclude-result-prefixes="NAME">
          
            <xsl:template match="node()|@*">
              <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
              </xsl:copy>
            </xsl:template>
          
            <xsl:template match="NAME:*">
              <xsl:element name="{name()}">
                <xsl:apply-templates select="node()|@*"/>
              </xsl:element>
            </xsl:template>
          
            <xsl:template match="ROOT">
              <xsl:element name="ROOT">
                <xsl:attribute name="xmlns:NAME">http://example.org/new</xsl:attribute>
                <xsl:apply-templates select="node()|@*"/>
              </xsl:element>
            </xsl:template>
          
          </xsl:stylesheet>
          Hier bekomme ich immer die Fehlermeldung:
          F:\XPress Project\XPress\EXP_namespace.xslt (22,7): Fehler: Das Präfix 'xmlns' wurde nicht definiert.
          Wenn ich jedoch das xmlns weglasse, dann bekomme ich im Prinzip wieder genau dasselbe Problem wie bei meinem vorherigen Beispiel, nämlich dass einfach der alte Namespace in die Kindelemente geschrieben wird.

          Ich hoffe das war jetzt verständlich formuliert. Vielen Dank schon einmal für alle Hilfen und Tipps!

          Mit freundlichen Grüßen,

          Florian Freitag

          Comment


          • #6
            exclude-result-prefixes="a oxml" ist bei der Ausgabe derselben nicht besonders sinnvoll. Probiere es mal so ({...} bei local-name() hinzugefügt und Namensräume bei xsl:stylesheet angepasst):
            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <xsl:stylesheet 
              version="1.0"
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            	xmlns="http://www.xpress-project.eu"
            	xmlns:a="http://www.xpress-project.eu#"
            	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#"> 
            
             <xsl:output method="xml" indent="yes"/>
            
             <xsl:template match="node() | @*">
                <xsl:copy>
                  <xsl:apply-templates select="node() | @*"/>
                </xsl:copy>
              </xsl:template>
            
              <xsl:template match="oxml:ontology">
                <oxml:ontology xmlns="http://www.xpress-project.eu"
                               xmlns:a="http://www.xpress-project.eu"
                  xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1">
                  <xsl:for-each select="*">
                    <xsl:call-template name="copy"/>
                  </xsl:for-each>
                </oxml:ontology>
              </xsl:template>
              
              <xsl:template name="copy">
                <xsl:element name="{local-name()}">
                  <xsl:copy-of select="@*"/>
                  <xsl:for-each select="*">
                    <xsl:call-template name="copy"/>
                  </xsl:for-each>
                </xsl:element>
              </xsl:template>
            
            </xsl:stylesheet>
            Ergebnis:
            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <!-- 
              xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#"  
              should be
              xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1" 
            -->
            <oxml:ontology xmlns="http://www.xpress-project.eu" xmlns:a="http://www.xpress-project.eu" xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1">
              <axiom>
                <text language="flogic"/>
              </axiom>
              <relation/>
            </oxml:ontology>

            Comment


            • #7
              Hallo Thomas,

              vielen Dank für den Tipp, das ist schon fast das gewünschte Ergebnis. Das Probelm ist noch, dass bei der aktuellen Transformation die Inhalte der Elemente und die Namespaces der Elemente verloren gehen. Die Inhalte mit zu kopieren, ist vermutlich kein Problem, doch bei den Namespaces, habe ich leider keine Ahnung.

              Das hier ist das Ergebnis:
              Code:
              <oxml:ontology xmlns="http://www.xpress-project.eu"
              	xmlns:a="http://www.xpress-project.eu"
              	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1">
                <axiom>
                  <text language="flogic"/>
                </axiom>
                <relation/>
              </oxml:ontology>
              So wäre es perfekt, wenn die Inhalte und Namespaces der Elemente erhalten bleiben würden:
              Code:
              <oxml:ontology
              	xmlns="http://www.xpress-project.eu"
              	xmlns:a="http://www.xpress-project.eu"
              	xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1">
                <oxml:axiom>
                  <oxml:text language="flogic">TEXT</oxml:text>
                </oxml:axiom>
                <oxml:relation />
              </oxml:ontology>
              Gibt es dafür eine praktikable Lösung?

              Mit freundlichen Grüßen,

              Florian Freitag

              Comment


              • #8
                Dann probiere es mit diesem copy-Template:
                Code:
                <xsl:template name="copy">
                  <xsl:element name="{name()}" namespace="http://schema.ontoprise.com/oxml/core/2.1">
                    <xsl:copy-of select="@*"/>
                    <xsl:for-each select="*">
                      <xsl:call-template name="copy"/>
                    </xsl:for-each>
                  </xsl:element>
                </xsl:template>

                Comment


                • #9
                  Merci, an das namespace-Attribut habe ich gar nicht gedacht.


                  Um den Inhalt der Elemente korrekt zu kopieren hatte ich noch folgende Zeile eingefügt. Die kopiert mir leider den Inhalt in das vorherige Element, dabei müsste ich doch eigentlich in dem aktuellen Element richtig sein oder?
                  Code:
                    <xsl:template name="copy">
                      <xsl:element name="{name()}" namespace="http://schema.ontoprise.com/oxml/core/2.1">
                        <xsl:copy-of select="@*"/>
                        <xsl:for-each select="*">
                          <xsl:value-of select="current()"/>
                          <xsl:call-template name="copy"/>
                        </xsl:for-each>
                      </xsl:element>
                    </xsl:template>
                  Die Ausgabe mit diesem Template:
                  Code:
                  <oxml:ontology 
                    xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1" 
                    xmlns="http://www.xpress-project.eu" 
                    xmlns:a="http://www.xpress-project.eu">
                    <oxml:axiom id="a:test">TEXT
                    <oxml:text language="flogic" />
                    </oxml:axiom>
                    <oxml:relation />
                  </oxml:ontology>
                  So sollte es aussehen (leicht verkürzt):
                  Code:
                    <oxml:axiom id="a:test">
                      <oxml:text language="flogic">TEXT
                      </oxml:text>
                    </oxml:axiom>
                  Viele Grüße,

                  Florian
                  Zuletzt editiert von Florian Freitag; 28.07.2009, 15:06.

                  Comment


                  • #10
                    Hallo,

                    ich muss mich noch einmal melden weil ich es offensichtlich nicht hinbekomme, dass der Elementinhalt korrekt kopiert wird.

                    Das Template zum Kopieren sieht mittlerweile so aus:
                    Code:
                      <xsl:template name="copy">
                        <xsl:element name="{name()}" namespace="http://schema.ontoprise.com/oxml/core/2.1">
                          <xsl:copy-of select="@*"/>
                          <xsl:if test="current() != ''">
                            <xsl:value-of select="."/>
                          </xsl:if>
                          <xsl:for-each select="*">
                            <xsl:call-template name="copy"/>
                          </xsl:for-each>
                        </xsl:element>
                      </xsl:template>
                    Dieses Template gibt bei folgender Ausgangsstruktur:
                    Code:
                    <oxml:axiom id="a:test">
                      <oxml:text language="flogic">TEXT der kopiert werden sollte!</oxml:text>
                    </oxml:axiom>
                    Die folgende Ausgabe:
                    Code:
                    <oxml:axiom id="a:test">
                        TEXT der kopiert werden sollte!
                      <oxml:text language="flogic">TEXT der kopiert werden sollte!</oxml:text></oxml:axiom>
                    Wie man leicht erkennen kann sollte der "erste" Text-Teil innerhalb des axiom-Elementes nicht stehen. Doch die Funktion xsl:value-of liefert leider auch für die Unterknoten den dortigen Textinhalt zurück. Die Frage ist jetzt, wie kann man das verhindern, so das nur der Textinhalt dessen Elementes ausgegeben wird, welches auch direkt den Textinhalt besitzt.

                    Die xsl:if-Abfrage ist in diesem Falle natürlich sinnbefreit, doch ich hatte gehoft mit einer geeigneten Bedinungn den notwendigen Zweck zu erfüllen. Nun denn ich hoffe einer von euch kann mir da weiterhelfen.

                    Mit freundlichen Grüßen,

                    Florian Freitag

                    Comment


                    • #11
                      Hallo,

                      ich wollte hier noch einmal kurz die Lösung des Problemes posten, falls jemand anderes auf eine ähnliche Aufgabenstellung stößt.

                      Code:
                      <?xml version="1.0" encoding="UTF-8"?>
                      
                      <!-- ################################################## -->
                      <!-- # Stylesheet Dekleration mit den alten Namespaces, außer dem 
                           # Default-Namespace, welcher schon neu ist. -->
                      <xsl:stylesheet
                        version="1.0"
                        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                        xmlns="http://www.xpress-project.eu"
                        xmlns:a="http://www.xpress-project.eu#"
                        xmlns:oxml="http://schema.ontoprise.com/oxml/core/2.1#"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
                        <!-- ################################################## -->
                      
                        <xsl:output method="xml" indent="yes"/>
                      
                        <xsl:template match="node() | @*">
                          <xsl:copy>
                            <xsl:apply-templates select="node() | @*"/>
                          </xsl:copy>
                        </xsl:template>
                      
                        <!-- ################################################## -->
                        <!-- # Schreibt den neuen Wurzelknoten mit den angepassten Namespaces.
                             # Ruft  nachdem Neuschreiben des Wurzelknotens das Template 'copy'
                             # auf, welches die Unterknoten des Dokuments kopiert. -->
                        <xsl:template match="oxml:ontology">
                          <oxml:ontology
                          xmlns="http://www.xpress-project.eu"
                          xmlns:a="http://www.xpress-project.eu"
                          xmlns:expl="http://schema.ontoprise.com/reserved">
                            <xsl:attribute name="id">
                              <xsl:value-of select="@id"/>
                            </xsl:attribute>
                            <xsl:for-each select="*">
                              <xsl:call-template name="copy"/>
                            </xsl:for-each>
                          </oxml:ontology>
                        </xsl:template>
                        <!-- ################################################## -->
                      
                        <!-- ################################################## -->
                        <!-- # Kopiert die Unterknoten des Wurzelknotens mit samt ihrem Inhalt,
                             # ohne dabei die alten Namespaces zu übernehmen. 
                             #
                             # Das Kopieren der Textinhalte ist so geregelt dass alle Knoten, 
                             # welche nach dem XSD Schema Text enthalten können, abgefragt werden
                             # und nur für diese deren Inhalt kopiert wird. Diese Lösung ist
                             # nicht die Beste, doch ist es leider nicht möglich einfach nur
                             # value-of für alle Knoten aufzurufen, da sonst der Text mehrfach
                             # in Oberknoten auch mit hineinkopiert wird. Darum diese Lösung 
                             # über die Abfrage des Knotennamens. -->
                        <xsl:template name="copy">
                          <xsl:element name="{name()}" namespace="http://schema.ontoprise.com/oxml/core/2.1">
                            <xsl:copy-of select="@*"/>
                            <xsl:if test="name() = ('oxml:text') or 
                                          name() = ('oxml:documentation') or
                                          name() = ('oxml:metaRelation') or
                                          name() = ('oxml:value') or
                                          name() = ('oxml:argument') or
                                          name() = ('oxml:externalRepresentation')">
                              <xsl:value-of select="."/>
                            </xsl:if>
                            <!--Alternative zur if-Abfrage: <xsl:value-of select="text()"/>-->
                            <xsl:for-each select="*">
                              <xsl:call-template name="copy"/>
                            </xsl:for-each>
                          </xsl:element>
                        </xsl:template>
                        <!-- ################################################## -->
                      
                      </xsl:stylesheet>
                      Vielleicht hilft das ja dem einen oder Anderem bei seinem Problem.

                      Mit freundlichen Grüßen,

                      Florian Freitag

                      Comment

                      Working...
                      X