从XSLT为ArrayOfString生成XML名称空间别名属性

时间:2014-10-30 10:42:00

标签: xml xslt xml-namespaces

我正在尝试使用XSLT将以下内容注入.exe.config文件:

<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属性存在,因为在ArrayOfString元素中没有使用xsi和xsd前缀。但这是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元素与我在问题开头所说的完全一致(这是一个配置文件升级方案)。

为什么会发生这种情况,如果不依靠引用我想要的片段,我想要的是什么呢?

1 个答案:

答案 0 :(得分:2)

就XPath数据模型而言,命名空间声明不是属性,您无法使用xsl:attribute 1 创建它们。但是,您不需要 - <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中不可用。