2014-10-30 166 views
0

我試圖使用XSLT注入以下爲.exe.config文件與:生成XML命名空間別名屬性ArrayOfString,從XSLT

<setting name="MySetting" serializeAs="Xml"> 
    <value> 
    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" /> 
    <string>test</string> 
    </value> 
</setting> 

說實話,我不知道爲什麼xmlns:xsixmlns:xsd屬性存在,因爲xsi和xsd前綴不在ArrayOfString元素內部使用。但是,這是由Visual Studio生成的用於設置字符串數組的類型的XML,並且我希望生成的XML與該數組匹配。

下面是輸入XML的簡化版本:

<?xml version="1.0" encoding="utf-8" ?> 
    <configuration> 
    <applicationSettings> 
    <MySettingsSection> 
    </MySettingsSection> 
    </applicationSettings> 
</configuration> 

這裏我最親密的XSL至今:

<?xml version="1.0" encoding="utf-8"?> 
<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" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <!-- Copy elements by default --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <!-- inject new element at the end of MySettingsSection --> 
    <xsl:template match="MySettingsSection"> 
    <xsl:copy> 
     <xsl:element name="setting"> 
     <xsl:attribute name="name">MySetting</xsl:attribute> 
     <xsl:attribute name="serializeAs">Xml</xsl:attribute> 
     <xsl:element name="value"> 
      <xsl:element name="ArrayOfString"> 
      <xsl:attribute namespace="xmlns" name="xmlns:xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute> 
      <xsl:attribute namespace="xmlns" name="xmlns:xsd">http://www.w3.org/2001/XMLSchema</xsl:attribute> 
      <xsl:element name="string">test</xsl:element> 
      </xsl:element> 
     </xsl:element> 
     </xsl:element> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

然而,這種輸出

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <applicationSettings> 
     <MySettingsSection> 
     <setting name="MySetting" serializeAs="Xml"> 
      <value> 
       <ArrayOfString xmlns:xp_0="xmlns" xp_0:xsi="http://www.w3.org/2001/XMLSchema-instance" xp_0:xsd="http://www.w3.org/2001/XMLSchema"> 
        <string>test</string> 
       </ArrayOfString> 
      </value> 
     </setting> 
     </MySettingsSection> 
    </applicationSettings> 
</configuration> 

注意在ArrayOfString元素中生成xp_0前綴(其名稱因XSLT引擎而異)。我可以看到,生成的XML大概是等價於我想要的,但我希望生成的ArrayOfStrings元素完全符合我在問題開始時提到的內容(這是配置文件升級方案)。

爲什麼會發生這種情況,這是我想要的,而不訴諸於我想要的字面上的片段?

+0

爲什麼你認爲「引用片段」是最後的手段?使用文字結果元素比使用'xsl:element'和'xsl:attribute'更加容易和優選,因爲只有在需要計算元素或屬性名稱和/或名稱空間時才需要這些元素。如果你想插入你有的片段,然後寫一個包含它的模板。 – 2014-10-30 11:39:11

+0

@MartinHonnen當我說「引用片段」時,我曾想過把它放在之內,並且不得不跳過所有的< >字符,這顯然非常難看,並且不會被XSLT引擎檢查有效性。我還沒有意識到XML元素可以在XSLT模板中直接使用。現在排序感謝伊恩羅伯特的答案。 – 2014-10-30 11:58:14

回答

2

就XPath數據模型而言,名稱空間聲明不是屬性,並且您不能使用xsl:attribute 來創建它們。但是,您不需要 - <xsl:element>僅在需要在運行時計算元素的名稱時才需要。如果您已經知道名稱,則可以使用literal result elements而不是xsl:element,並且在文字結果元素上聲明的任何名稱空間應該自動遍歷到輸出樹上(假定它們尚未在較高級別聲明)。

<xsl:template match="MySettingsSection"> 
    <xsl:copy> 
    <setting name="MySetting" serializeAs="Xml"> 
     <value> 
     <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" /> 
     <string>test</string> 
     </value> 
    </setting> 
    </xsl:copy> 
</xsl:template> 

1.您可以在XSLT 2.0中使用xsl:namespace,但選項不可用在XSLT 1.0。

+0

太簡單了!謝謝。 – 2014-10-30 11:53:06