2010-11-18 16 views
3

Ich habe diese xml umbenennen:ein Element mit Xslt

<pos:getPositionRouter xmlns:pos="positionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</pos:getPositionRouter> 

und ich möchte das Element pos:getPositionRouter zu x:getPosition mit Xslt umbenennen:

<x:getPosition xmlns:x="newPositionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</x:getPosition> 

Dies ist sylesheet kam ich mit:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" /> 

<xsl:param name="old_namespace" /> 
<xsl:param name="old_element_localname" /> 
<xsl:param name="new_namespace" /> 
<xsl:param name="new_element_localname" /> 


<xsl:template match="@*|node()"> 
    <xsl:choose> 
    <xsl:when test="(local-name() = $old_element_localname) and (namespace-uri() = $old_namespace)"> 
    <xsl:element name="{$new_element_localname}" namespace="{$new_namespace}"> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
    </xsl:when> 

    <!-- copy the rest as is --> 
    <xsl:otherwise> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()" /> 
    </xsl:copy> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

Ich bin gezwungen, xalan als xslt Prozessor zu verwenden, und die Ausgabe ist leider das:

<getPosition xmlns="newPositionNS"> 
    <positionID xmlns:pos="positionNS"> 
     <code>1</code> 
    </positionID> 
    <parameter xmlns:pos="positionNS">?</parameter> 
</getPosition> 

Der Standard-Namespace des getPosition Element wird zum neuen Namensraum, aber die untergeordneten Elemente ohne Namensraum (xmlns="") bleiben sollte.

Kann jemand verstehen warum?

Vielen Dank!

+0

Sie beachten Sie, dass Sie den gewünschten Ausgang und dem tatsächlichen Ausgang semantisch gleich sind: '{} newPositionNS getPosition' Kinder unter null NamespaceURI, haben sie nur eine "positionNS" Namespace-URI im Bereich (wird jedoch nicht verwendet). –

+0

Hallo Alejandro, wie ich es verstehe, die beiden Ausgaben sind nicht semantisch gleich: die Standard-Namespace-Einstellung xmlns = "newPositionNS" auf dem Root-Element wird an die Childs vererbt, so PositionID ist jetzt in der NewPositionNS Namespace, und nicht in der " "Namensraum wie er sollte. – Simon

+0

Gute Frage, +1. Siehe meine Antwort für eine kurze und einfache Lösung. :) –

Antwort

1

Dieses Sheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:param name="old_namespace" select="'positionNS'"/> 
    <xsl:param name="old_element_localname" select="'getPositionRouter'"/> 
    <xsl:param name="new_namespace_prefix" select="'x'"/> 
    <xsl:param name="new_namespace" select="'newPositionNS'"/> 
    <xsl:param name="new_element_localname" select="'getPosition'" /> 
    <xsl:template match="*"> 
     <xsl:choose> 
      <xsl:when test="local-name()=$old_element_localname and 
          namespace-uri()=$old_namespace"> 
       <xsl:element 
        name="{substring(concat($new_namespace_prefix,':'), 
             1 div boolean($new_namespace_prefix))}{ 
          $new_element_localname}" 
        namespace="{$new_namespace}"> 
        <xsl:apply-templates select="@*|node()"/> 
       </xsl:element> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:element name="{name()}"> 
        <xsl:apply-templates select="@*|node()"/> 
       </xsl:element> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
    <xsl:template match="@*"> 
     <xsl:attribute name="{name()}"> 
      <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

Ausgang:

<x:getPosition xmlns:x="newPositionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</x:getPosition> 

Hinweis: Wenn Sie ein bestimmtes Präfix wollen, sollten Sie es auf den QName hinzufügen. Wenn Sie Namespace-in-scope entfernen möchten, sollten Sie xsl:copy nicht in XSLT 1.0

+0

Awesome, danke Alejandro, ich möchte nicht wirklich das Namespacepräfix erzwingen, das 'x' war nur ein Beispiel, aber es könnte alles sein, das ist nicht wichtig. Wichtig ist, dass die Child-Elemente keinen Namensraum haben. – Simon

+0

@Luca: Sie sind willkommen. Überprüfen Sie meinen Kommentar zu Ihren Fragen. Vielleicht solltest du einen Fehler in Xalan melden. –

0

I. Die Umwandlung, dies zu tun, ohne Parameter verwendet, ist wirklich kurz und einfach:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:pos="positionNS" xmlns:x="newPositionNS" > 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="pos:getPositionRouter"> 
    <xsl:element name="x:getPosition"> 
    <xsl:apply-templates/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:element name="{name()}"> 
    <xsl:copy-of select="namespace::*[not(name()='pos')]"/> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

bei der Anwendung das bereitgestellten XML-Dokument:

<pos:getPositionRouter xmlns:pos="positionNS"> 
    <positionID> 
     <code>1</code> 
    </positionID> 
    <parameter>?</parameter> 
</pos:getPositionRouter> 

das gewünschte, wird korrektes Ergebnis erzeugt:

<x:getPosition xmlns:x="newPositionNS"> 
    <positionID> 
     <code>1</code>1 
    </positionID> 
    <code>1</code>1 
    <parameter>?</parameter>? 
</x:getPosition> 

II. Die parametrisierte Transformation ist nur ein wenig komplexer:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:param name="pOldNamespace" select="'positionNS'"/> 
<xsl:param name="pOldElementLocalname" select="'getPositionRouter'"/> 
<xsl:param name="pNewNamespace" select="'newPositionNS'"/> 
<xsl:param name="pNewElementLocalname" select="'getPosition'"/> 
<xsl:param name="pNewElementPrefix" select="'x'"/> 

<xsl:template match="*"> 
    <xsl:variable name="vReplacing" select= 
    "local-name()=$pOldElementLocalname 
    and 
    namespace-uri()=$pOldNamespace"/> 

    <xsl:variable name="vName"> 
    <xsl:choose> 
    <xsl:when test="$vReplacing"> 
    <xsl:value-of select="concat($pNewElementPrefix, ':', local-name())"/> 
    </xsl:when> 
    <xsl:otherwise><xsl:value-of select="name()"/></xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="vNamespace"> 
    <xsl:choose> 
    <xsl:when test="$vReplacing"> 
    <xsl:value-of select="$pNewNamespace"/> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:value-of select="namespace-uri()"/> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:element name="{$vName}" namespace="{$vNamespace}"> 
    <xsl:copy-of select="namespace::*[not(.=$pOldNamespace)]"/> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 
</xsl:stylesheet> 
+0

@Dimitre: Abgesehen davon, dass die Parametrisierung eine Anfrage war, und die gute Methode, nur einen bestimmten in-scope-Namespace zu stripen, sollten Sie Ihr Stylesheet noch einmal überprüfen: auf Attribute ohne Attributregel und ein anwenden Tippfehler in der Regel "jedes Element". –

+0

@Alejandro: Ich weiß gut, dass ich Attribute - absichtlich vermisste, da es keine Attribute in der Quell-XML gibt. Was die Parametrierung betrifft - sie ist nur im mitgelieferten Code zu sehen, den ich gar nicht gelesen habe ... Ich bin mir nicht sicher, ob die Parametrierung eine Voraussetzung ist. –

+0

+1 Ich mag die Variablendeklaration für Name und Namespace, macht das Stylesheet lesbarer. –

Verwandte Themen