XSL – Elemente kopieren, aber nicht verwendete Namespace(s) entfernen
-
21-08-2019 - |
Frage
Ich habe XML, das einen Namespace deklariert, der nur für Attribute verwendet wird, etwa so:
<?xml version="1.0" encoding="UTF-8"?>
<a xmlns:x="http://tempuri.com">
<b>
<c x:att="true"/>
<d>hello</d>
</b>
</a>
Ich möchte XSL verwenden, um eine Kopie ausgewählter Knoten und ihrer Werte zu erstellen und die Attribute zu entfernen.Meine gewünschte Ausgabe ist also:
<?xml version="1.0" encoding="UTF-8"?>
<b>
<c />
<d>hello</d>
</b>
Ich habe XSL, das das fast macht, aber ich kann es scheinbar nicht verhindern, dass die Namespace-Deklaration in das Element der obersten Ebene der Ausgabe eingefügt wird.Mein XSL ist:
<?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="/a/b"/>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Das erste Element der Ausgabe ist <b xmlns:x="http://tempuri.com">
anstatt <b>
.Ich habe versucht, den Namespace im XSL zu deklarieren und das Präfix in das einzufügen exclude-result-prefixes
Liste, aber das scheint keine Auswirkung zu haben.Was mache ich falsch?
AKTUALISIEREN:Ich habe das herausgefunden, indem ich den Namespace im XSL deklariert und verwendet habe extension-element-prefixes
Attribut funktioniert, aber das scheint nicht richtig zu sein!Ich schätze, ich könnte das gebrauchen, aber ich würde gerne wissen, warum exclude-result-prefixes
funktioniert nicht!
AKTUALISIEREN:Tatsächlich sieht es so aus extension-element-prefixes
Die Lösung funktioniert nur mit der integrierten XSLT-Engine von XMLSpy, nicht mit MSXML.
Lösung
<?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="/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>
Ich fand eine Erklärung hier .
Michael Kay schrieb:
exclude-Ergebnis-Präfixe nur die aus den kopierten Namespaces beeinflusst Sheet von einem literalen Ergebniselement, es wirkt sich nicht auf das Kopieren von Namespaces von Quelldokumenten.
Andere Tipps
<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>
Versuchen Sie dies (das Attribut copy-namespaces='no'
beachten):
<xsl:template match="node()">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
Dadurch wird der x-Namespace aus der Ausgabe entfernt.
<xsl:namespace-alias result-prefix="#default" stylesheet-prefix="x" />
Denken Sie daran, zwei Dinge zu tun, wenn Sie mit einem Standard-Namespace arbeiten.Ordnen Sie es zunächst einem Element im Stylesheet-Tag zu und entfernen Sie es dann mithilfe eines Namespace-Alias.