2016-07-01 17 views
1

Die Frage ist, wie folgt, ich habe eine einfache XML-Datei:Überschreibungs Xmlns bricht Xslt Ergebnis

<table xmlns="http://www.w3.org/TR/html4/"> 
    <tr> 
     <td> 
      Does not work 
     </td> 
    </tr> 
</table> 

Und eine XSL tranformation Datei

<xsl:transform version="1.0" xmlns="http://www.w3.org/TR/html4/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="td"> 
     It works 
    </xsl:template> 
</xsl:transform> 

Wenn "td" wird angepasst erwarte ich, um zu sehen "Es funktioniert" als Ausgabe wie in der Vorlage definiert. Wenn "td" nicht übereinstimmt, dann erwarte ich "Does not work", da die Standardvorlagen alle Knotenwerte ausgeben, die nicht von einer benutzerdefinierten Vorlage verarbeitet werden. Ergebnis:

<?xml version="1.0"?> 


     Does not work 

Allerdings, wenn ich die Namespace-Deklarationen zu Xmlns ändern: html = "...", dann ändert sich das Ergebnis.

xml:

<html:table xmlns:html="http://www.w3.org/TR/html4/"> 
    <html:tr> 
     <html:td> 
      Does not work 
     </html:td> 
    </html:tr> 
</html:table> 

Xslt:

<xsl:transform version="1.0" xmlns:html="http://www.w3.org/TR/html4/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="html:td"> 
     It works 
    </xsl:template> 
</xsl:transform> 

Ergebnis:

<?xml version="1.0"?> 


    It works 

Dies ist ein einfaches Beispiel, das Problem zu isolieren, die XML für die reale Anwendung wird zur Verfügung gestellt von Software von Drittanbietern, Xmlns-Deklaration zu Xmlns überschreiben: ist keine Option. Meine Frage ist, wie bekomme ich dies zur Arbeit, Ergebnis: "Es funktioniert", ohne xmlns zu ändern.

Für die Konvertierung verwende ich Notepad ++ mit XML-Tools-Plugin, wo es eine XSL-Transformation-Option gibt.

Vielen Dank im Voraus

Antwort

3

Trans das erste Dokument (das eine, die einen Standard Namespace):

<table xmlns="http://www.w3.org/TR/html4/"> 
    <tr> 
     <td> 
      Does not work 
     </td> 
    </tr> 
</table> 

mit dem zweiten XSLT-Stylesheet:

<xsl:transform version="1.0" xmlns:html="http://www.w3.org/TR/html4/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="html:td"> 
     It works 
    </xsl:template> 
</xsl:transform> 

und Sie werden überrascht sein, durch das Ergebnis:

<?xml version="1.0" encoding="UTF-8"?> 


    It works 

Deklarieren einen Namespace mit einem Präfix:

xmlns:html="http://www.w3.org/TR/html4/" 

ist die übliche Art und Weise mit XML-Eingabedokumenten zu behandeln, die einen Standard-Namespace haben. Wenn Sie eine solche Deklaration in Ihrem Stylesheet haben, bedeutet html:td genau dasselbe wie das td Element mit einem Standardnamespace aus dem Eingabedokument.

Dies ist, weil Präfixe sind eigentlich irrelevant.Präfixe wie html: haben keine Bedeutung, es ist der Namespace-URI, der aussagekräftig ist. Präfixe sind nur eine Kurzform, um zu vermeiden, den Namespace-URI für jedes einzelne Element eingeben (oder lesen) zu müssen. Sie sollten wie

ein Element denken
<table xmlns="http://www.w3.org/TR/html4/"> 

als

<{http://www.w3.org/TR/html4/}table> 

und analog denken

<html:table xmlns:html="http://www.w3.org/TR/html4/"> 

als das gleiche:

<{http://www.w3.org/TR/html4/}table> 

Auch kurz kommentiert:

<xsl:transform version="1.0" xmlns="http://www.w3.org/TR/html4/"> 

daran erinnern, dass ein Stylesheet nur eine ganz normale XML-Datei und alle Regeln von XML für sie gelten. Der einzige Effekt, einen Standard-Namespace in einem XSLT-Stylesheet zu deklarieren, ist folgender: Alle Elemente, die kein Präfix haben (d. H. Sich in keinem anderen Namespace befinden), werden diesem Namespace zugeordnet.

Da jedoch alle Elemente in Ihrem XSLT-Stylesheet das Präfix xsl: haben, macht der Standardnamespace nichts. In einem Stylesheet wie:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform version="1.0" xmlns="http://www.w3.org/TR/html4/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <result>it works</result> 
    </xsl:template> 
</xsl:transform> 

können Sie tatsächlich sehen, was der Standard-Namespace der Fall ist, da das Ergebnis sein wird:

<?xml version="1.0" encoding="UTF-8"?> 
<result xmlns="http://www.w3.org/TR/html4/">it works</result> 
+0

Das löst das Problem, aber ich verstehe immer noch nicht, warum nicht das Voranstellen funktioniert nicht. Wenn kein Präfix vorhanden ist, wird der Namespace, der von xmlns deklariert wird, nicht standardmäßig verwendet, da es keinen Konflikt mit einem anderen Namespace gibt, von dem ich erwartet habe, dass dies funktioniert. – DemanB

+0

@DemanB "* Wenn es kein Präfix gibt, ist es kein Standard für den Namespace, der von xmlns deklariert wird." Wenn es kein Präfix gibt, wird es Elemente in keinem Namespace auswählen. –

+1

@DemanB Bitte lassen Sie mich versuchen, dies noch einmal zu erklären: Ihre Annahme ist, dass in 'xsl: template' -Elementen ein im' xsl: transform'-Element deklarierter Standard-Namespace auf den Wert des 'select'-Attributs angewendet wird. Standard-Namespaces werden jedoch immer nur auf XML-Elemente angewendet, niemals auf Attribute und niemals auf die Werte von Attributen. Es gibt Funktionalität, die dies tut, obwohl ich es in diesem Fall nicht empfehle: ['xpath-default-namespace'] (https://www.ibm.com/developerworks/library/x-xsltmistakes/#list4). Außerdem benötigt es XSLT 2.0. –

1

Meine Frage ist, wie bekomme ich das, Ergebnis zu arbeiten: „Es funktioniert“, ohne Wechsel Xmlns.

<xsl:transform version="1.0" 
xmlns:ns="http://www.w3.org/TR/html4/" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="ns:td"> 
     It works 
</xsl:template> 

</xsl:transform> 
+0

Dies ist eine richtige Antwort, akzeptiert die Antwort von Mathias Müller für die zusätzliche Informationen . Danke – DemanB

+0

"* hat die Antwort von Mathias Müller für die Zusatzinformation angenommen. *" Und das solltest du auch! –