2009-07-02 5 views
18

Ho un po 'di XML che dichiara uno spazio dei nomi che viene utilizzato solo per gli attributi, come questo:XSL - copia elementi, ma rimuovere namespace non utilizzati (s)

<?xml version="1.0" encoding="UTF-8"?> 
<a xmlns:x="http://tempuri.com"> 
    <b> 
     <c x:att="true"/> 
     <d>hello</d> 
    </b> 
</a> 

voglio utilizzare XSL per creare una copia dei nodi selezionati e dei loro valori - eliminando gli attributi. Quindi il mio output desiderato è:

<?xml version="1.0" encoding="UTF-8"?> 
<b> 
    <c /> 
    <d>hello</d> 
</b> 

Ho alcune XSL che fa quasi questo, ma io non riesco a fermarlo mettere la dichiarazione dello spazio dei nomi nell'elemento alto livello dell'uscita. Il mio XSL è:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="https://stackoverflow.com/a/b"/> 
    </xsl:template> 

    <xsl:template match="node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

Il primo elemento della produzione è <b xmlns:x="http://tempuri.com"> invece di <b>. Ho provato a dichiarare lo spazio dei nomi nell'XSL e inserire il prefisso nell'elenco exclude-result-prefixes, ma questo non sembra avere alcun effetto. Che cosa sto facendo di sbagliato?

AGGIORNAMENTO: Ho scoperto che dichiarando lo spazio dei nomi nell'XSL e utilizzando l'attributo extension-element-prefixes funziona, ma questo non sembra giusto! Immagino di poterlo usare, ma mi piacerebbe sapere perché lo exclude-result-prefixes non funziona!

AGGIORNAMENTO: In realtà, sembra che questa soluzione extension-element-prefixes funzioni solo con il motore XSLT incorporato di XMLSpy, non con MSXML.

risposta

9
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
    xmlns:x="http://tempuri.com"> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="https://stackoverflow.com/a/b"/> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:element name="{local-name(.)}"> 
      <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:copy/> 
    </xsl:template> 

    <!-- This empty template is not needed. 
Neither is the xmlns declaration above: 
    <xsl:template match="@x:*"/> --> 
</xsl:stylesheet> 

Ho trovato una spiegazione here.

Michael Kay ha scritto:
escludono-risultato-prefissi riguarda solo gli spazi dei nomi copiati dalla foglio di stile da un elemento risultato letterale, non influenza la copia di spazi dei nomi da documenti di origine.

+0

Grazie, questo funziona (anche se il modello "@ *" non sembra essere richiesto), ma ho pensato che il nome locale"() "la funzione era piuttosto lenta ..? –

+1

Voglio XSLT 2.0! – Riri

+0

Quasi perfetto, ma l'attributo x: att manca nell'output. Il modello "@ *" non è invocato. Prova ad aggiungere direttamente prima di . –

5
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:x="http://tempuri.com" 
    exclude-result-prefixes="x" 
> 

    <!-- the identity template copies everything 1:1 --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()" /> 
    </xsl:copy> 
    </xsl:template> 

    <!-- this template explicitly cares for namespace'd attributes --> 
    <xsl:template match="@x:*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="." /> 
    </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 
2

Questo rimuoverà la x namespace dall'uscita.

<xsl:namespace-alias result-prefix="#default" stylesheet-prefix="x" /> 

ricordarsi di fare due cose quando avete a che fare con uno spazio dei nomi predefinito. Per prima cosa mappalo in qualcosa nel tag del foglio di stile, quindi rimuovilo usando un alias dello spazio dei nomi.

4

Prova questa (si noti l'attributo copy-namespaces='no'):

<xsl:template match="node()"> 
    <xsl:copy copy-namespaces="no"> 
      <xsl:apply-templates select="node()"/> 
    </xsl:copy> 
</xsl:template>