如何使用xslt更改xml中的命名空间

时间:2017-08-30 13:49:22

标签: .net xml xslt

我需要将xml中的所有属性转换为具有某些条件的元素。比如说一些属性应该以" Value"为前缀。它。我做到了这一点。除此之外,我还需要更改我的命名空间。我无法做到这一点。

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>

输出

<?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#转换它。

请帮我解决这个问题。

2 个答案:

答案 0 :(得分:1)

要更改所有元素的命名空间,您可以使用xsl:element属性使用namespace重新构建它们。因此,以下代码更改了两个模板,并添加了一个通用&#34; use-new-namespace&#34;模板:

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

答案 1 :(得分:0)

实现目标的一种方法是使用新命名空间重写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:Style | 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>