2017-08-30 79 views
0

我需要將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#進行轉換。

請幫我解決這個問題。

回答

1

要改變命名空間全部您可以使用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> 
+0

我很抱歉,我無法理解。你能否詳細說明一下? – shanmugharaj

+0

簡而言之,添加上面的第一個模板,並在XSLT中更改其他兩個模板。然後每個元素都會得到新的名稱空間。 – zx485

+0

我現在還有一個問題。這是我需要做的一項新增強。實際上,在爲符號' default.png'寫入輸出時,根據Name屬性中的內容包含'png'或'dwg',name屬性必須以C:\或C:\ dwg \爲前綴。我試着把這個條件放在這個''裏面。但我無法得到這個工作。你能幫我解決這個問題嗎? – shanmugharaj

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:風格| 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> 
+0

你不覺得OP可能希望將新的名稱空間應用於_all_元素,並且舊的名稱空間基本上被丟棄了? – kumesana