2009-07-02 11 views
18

Mam trochę XML, który deklaruje nazw, który jest używany tylko dla atrybutów, na przykład:XSL - kopiować elementy, ale usunąć niewykorzystaną przestrzeń nazw (-y)

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

Chcę użyć XSL, aby utworzyć kopię wybranych węzłów i ich wartości - pozbycie się atrybutów. Więc moja pożądane wyjście jest:

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

Mam trochę XSL, że prawie tego nie robi, ale nie mogę się powstrzymać to oddanie deklaracji przestrzeni nazw w górnym elemencie poziomu wyjścia. Moje XSL jest:

<?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> 

Pierwszym elementem produkcji jest <b xmlns:x="http://tempuri.com"> zamiast <b>. Próbowałem już zadeklarować przestrzeń nazw w XSL i umieszczając prefiks na liście exclude-result-prefixes, ale wydaje się, że nie ma to żadnego wpływu. Co ja robię źle?

AKTUALIZACJA: Zauważyłem, że deklarując przestrzeń nazw w XSL i używając atrybutu extension-element-prefixes działa, ale to nie wydaje się właściwe! Myślę, że mógłbym użyć tego, ale chciałbym wiedzieć, dlaczego exclude-result-prefixes nie działa!

AKTUALIZACJA: Wydaje się, że to rozwiązanie działa tylko z wbudowanym silnikiem XSLT XMLSpy, a nie z MSXML.

Odpowiedz

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> 

Znalazłem wyjaśnienie here.

Michael Kay napisał:
wykluczyć-result-prefiksy dotyczy tylko nazw kopiowanych z arkusza przez dosłownym elementu wynikowego, to nie ma wpływu na kopiowanie nazw z dokumentów źródłowych.

+0

Dzięki, to działa (choć szablon "@ *" nie wydaje się być konieczne), ale myślałem, że „local-name () "funkcja była dość powolna ..? –

+1

Chcę XSLT 2.0! – Riri

+0

Prawie idealnie, ale atrybut x: att nie występuje w danych wyjściowych. Szablon "@ *" nie jest wywoływany. Spróbuj dodać bezpośrednio przed . –

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

To usunie x nazw od wyjścia.

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

Pamiętaj, aby zrobić dwie rzeczy, gdy masz do czynienia z domyślnym obszarem nazw. Najpierw zmapuj go w coś w tagu arkusza stylów, a następnie usuń za pomocą aliasu przestrzeni nazw.

4

Spróbuj tego (uwaga atrybut copy-namespaces='no'):

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