如何使用xslt更改xml中的名称空间
我需要将xml中的所有属性转换为具有某些条件的元素。举例来说,一些属性应该以“Value”作为前缀。我实现了这个目标。除此之外,我还需要更改我的名称空间。我无法做到这一点。如何使用xslt更改xml中的名称空间
XML
<Template xmlns="styling/1.0.0" Name="TemplateFromDictionary">
<Style Name="Default">
<Fill Color=""/>
<Stroke Color="0000FF" LineStyle="Single" Width="1"/>
<Symbol Color="FFFFFF" Name="default.png" ScaleX="100" ScaleY="100" ScaleMode="Drawing"/>
</Style>
<Style Name="Parcel">
<Fill Color="48F5F5F5"/>
<Stroke Color="C0C0C0" LineStyle="Single" Width="1"/>
<Symbol Color="FFFFFF" Name="default.png" ScaleX="100" ScaleY="100" ScaleMode="Drawing"/>
</Style>
</Template>
XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
xmlns:s="styling/1.0.0"
xmlns="styling/1.0.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="s:Style|s:Template">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:variable name="name">
<xsl:apply-templates select="." mode="name"/>
</xsl:variable>
<xsl:element name="{$name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="@Color|@Width|@ScaleX|@ScaleY|@LeftIndent|@RightIndent|@FirstLineIndent|@SpaceBefore|@SpaceAfter|@Size" mode="name">
<xsl:value-of select="concat(name(), 'Value')"/>
</xsl:template>
<xsl:template match="@*" mode="name">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet>
OUTPUT
<?xml version="1.0" encoding="utf-8"?>
<Template Name="TemplateFromDictionary" xmlns="styling/1.0.0">
<Style Name="Default">
<Fill>
<ColorValue></ColorValue>
</Fill>
<Stroke>
<ColorValue>0000FF</ColorValue>
<LineStyle>Single</LineStyle>
<WidthValue>1</WidthValue>
</Stroke>
<Symbol>
<ColorValue>FFFFFF</ColorValue>
<Name>default.png</Name>
<ScaleXValue>100</ScaleXValue>
<ScaleYValue>100</ScaleYValue>
<ScaleMode>Drawing</ScaleMode>
</Symbol>
</Style>
<Style Name="Parcel">
<Fill>
<ColorValue>48F5F5F5</ColorValue>
</Fill>
<Stroke>
<ColorValue>C0C0C0</ColorValue>
<LineStyle>Single</LineStyle>
<WidthValue>1</WidthValue>
</Stroke>
<Symbol>
<ColorValue>FFFFFF</ColorValue>
<Name>default.png</Name>
<ScaleXValue>100</ScaleXValue>
<ScaleYValue>100</ScaleYValue>
<ScaleMode>Drawing</ScaleMode>
</Symbol>
</Style>
</Template>
在输出,而不是这个
<Template Name="TemplateFromDictionary" xmlns="styling/1.0.0">
我需要这个
<Template Name="TemplateFromDictionary" xmlns="styling/2.0.0">
我试图通过改变XSLT的命名空间xmlns="styling/2.0.0"
但是,这是给像
<Fill><ColorValue xmlns="styling/2.0.0"></ColorValue></Fill>
命名空间中的结果嵌入到所有元素和Template元素看起来相同
<Template Name="TemplateFromDictionary" xmlns="styling/1.0.0">
我需要的输出与上面提到的输出完全相同,只是需要更改Template元素中的名称空间。
我正在用C#进行转换。
请帮我解决这个问题。
要改变命名空间全部您可以使用namespace
属性使用xsl:element
重建它们的元素。所以,下面的代码改变两个模板,并增加了一个一般的“使用新的命名空间”模板:
<!-- use-new-namespace template for all s:* elements -->
<xsl:template match="s:*">
<xsl:element name="{local-name()}" namespace="styling/2.0.0">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<!-- modified templates for new namespace -->
<xsl:template match="s:Style|s:Template">
<xsl:element name="{local-name()}" namespace="styling/2.0.0">
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:variable name="name">
<xsl:apply-templates select="." mode="name"/>
</xsl:variable>
<xsl:element name="{$name}" namespace="styling/2.0.0">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
所以整个XSLT文件:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
xmlns:s="styling/1.0.0"
xmlns:t="styling/2.0.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- use-new-namespace template for s:* elements -->
<xsl:template match="s:*">
<xsl:element name="{local-name()}" namespace="styling/2.0.0">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<!-- modified templates for new namespace -->
<xsl:template match="s:Style|s:Template">
<xsl:element name="{local-name()}" namespace="styling/2.0.0">
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:variable name="name">
<xsl:apply-templates select="." mode="name"/>
</xsl:variable>
<xsl:element name="{$name}" namespace="styling/2.0.0">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="@Color|@Width|@ScaleX|@ScaleY|@LeftIndent|@RightIndent|@FirstLineIndent|@SpaceBefore|@SpaceAfter|@Size" mode="name">
<xsl:value-of select="concat(name(), 'Value')"/>
</xsl:template>
<xsl:template match="@*" mode="name">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet>
实现您的目标的一种方法是用新的名称空间重写Template元素。例如:添加下面的模板到您的XSLT:
<xsl:template match="s:Style">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="s:Template" xmlns:ns2="styling/2.0.0">
<ns2:Template>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</ns2:Template>
</xsl:template>
,取出旧S:风格| S:模板匹配模板
更清晰:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
xmlns:s="styling/1.0.0"
xmlns="styling/1.0.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!--
<xsl:template match="s:Style|s:Template">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
-->
<xsl:template match="s:Style">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="s:Template" xmlns:ns2="styling/2.0.0">
<ns2:Template>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</ns2:Template>
</xsl:template>
<xsl:template match="@*">
<xsl:variable name="name">
<xsl:apply-templates select="." mode="name"/>
</xsl:variable>
<xsl:element name="{$name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="@Color|@Width|@ScaleX|@ScaleY|@LeftIndent|@RightIndent|@FirstLineIndent|@SpaceBefore|@SpaceAfter|@Size" mode="name">
<xsl:value-of select="concat(name(), 'Value')"/>
</xsl:template>
<xsl:template match="@*" mode="name">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet>
你不觉得OP可能希望将新的名称空间应用于_all_元素,并且旧的名称空间基本上被丢弃了? – kumesana
我很抱歉,我无法理解。你能否详细说明一下? – shanmugharaj
简而言之,添加上面的第一个模板,并在XSLT中更改其他两个模板。然后每个元素都会得到新的名称空间。 – zx485
我现在还有一个问题。这是我需要做的一项新增强。实际上,在为符号' default.png '写入输出时,根据Name属性中的内容包含'png'或'dwg',name属性必须以C:\或C:\ dwg \为前缀。我试着把这个条件放在这个''里面。但我无法得到这个工作。你能帮我解决这个问题吗? –
shanmugharaj