在向XML文件添加元素时,停止包含xmlns属性的XSLT

时间:2011-12-06 16:23:18

标签: xslt web-config elmah

背景:我正在尝试编写Elmah的配置脚本,这样,在生产中,我可以运行一个脚本来复制二进制文件并相应地编辑web.config文件。

我决定使用XSLT对web.config文件进行更改。首先,我想在sectionGroup元素中添加configSections

  <sectionGroup name="elmah">
    <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    ....
  </sectionGroup>

这是我的XSLT模板

<?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"
    xmlns:con="http://schemas.microsoft.com/.NetConfiguration/v2.0"
>
    <xsl:output method="xml" indent="yes"/>

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

  <!-- Add sectionGroup to configuration/configSections-->
  <xsl:template match="con:configSections[not (con:sectionGroup/@name='elmah')]">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
      <xsl:comment>ELMAH</xsl:comment>
      <sectionGroup name="elmah" >
        <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
        <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
        <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
        <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
      </sectionGroup>
      <xsl:comment>/ELMAH</xsl:comment>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

它几乎可以满足我的需求。它生成以下sectionGroup XML。

  <!--ELMAH-->
  <sectionGroup name="elmah" xmlns="" xmlns:con="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
    ....
  </sectionGroup>
  <!--/ELMAH-->

请注意xmlns属性。这个属性的存在确实扰乱了ASP.Net(即使它是完全有效的XML - 尽管是多余的),并且所有请求都会导致HTTP 500错误(请参阅下面的部分以获取错误消息)。唯一可以从

中获取的错误消息

删除xmlns属性可以解决此问题。

我可以使用xsl:element生成新的XML,但这会导致非常冗长且难以阅读的XSL。

所以我的问题是如何告诉XSLT 在生成的XML中添加xmls属性?

提前致谢。


错误消息

这里的信息是ASP / IIS为我们提供的错误消息: -

  • 当配置文件的根元素(或任何其他元素)具有前缀定义xmlns:con="http://schemas.microsoft.com/.NetConfiguration/v2.0"时,我在YSOD中得到以下内容

    配置错误

    描述:处理为此请求提供服务所需的配置文件时发生错误。请查看下面的具体错误详细信息并相应地修改配置文件。

    分析器错误消息:无法识别的属性'xmlns:con'。请注意,属性名称区分大小写。

  • 当任何其他元素具有'xmlns'属性属性时,我在YSOD中收到以下消息。

    分析器错误消息:无法识别的属性“xmlns”。请注意,属性名称区分大小写。

  • 在其他情况下(我尚未解决)我没有得到YSOD,只是IIS的默认500页。尽管启用了失败的请求跟踪,但我没有得到任何日志。这可能是PEBKAC。


我的问题的解决方案

感谢LarsH,Vincent Biragnet和Michael Kay的回复,他们之间已经解决了我的问题。

首先 - 我发布的XSLT错误,正如Michael和Vincent所指出的那样,sectionGroup元素位于名称空间“http://schemas.microsoft.com/.NetConfiguration/v2中。 0" 。

为了对此进行排序,我在我的XSLT中定义了默认命名空间,如xmlns="http://schemas..."

但是(为什么我不知道)sectionGroup元素然后输出为

<sectionGroup name="elmah" xmlns:con="http://schemas.microsoft.com/.NetConfiguration/v2.0">

(xmlns:con不是多余的吗?)。无论如何,配置解析器barfs存在xmlns:con。

但LarsH拯救 - 他建议使用exclude-result-prefixes="msxsl con"的建议摆脱了那些讨厌的事情。

所以我的(现在正在工作)XSLT的顶部现在看起来像这样

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:con="http://schemas.microsoft.com/.NetConfiguration/v2.0"
    xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"
    exclude-result-prefixes="msxsl con"
>

再次感谢大家的帮助

4 个答案:

答案 0 :(得分:1)

在有关con:configSections元素的模板中,添加了一个不合格的sectionGroup元素,没有与之关联的命名空间。

尝试将sectionGroup部分替换为:

  <con:sectionGroup name="elmah" >
    <con:section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
    <con:section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
    <con:section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
    <con:section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
  </con:sectionGroup>

如果假设sectionGroup必须与configSection位于同一名称空间中。

另一种方法是保持代码不带前缀,并在sectionGroup标记中添加以下命名空间声明:xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"

答案 1 :(得分:1)

在XSLT数据模型中,名称空间声明和未声明属性不是属性节点。不要考虑名称空间声明和未声明:而是考虑元素的名称。您想要一个名称(使用符号(uri,local))

的元素

(“http://schemas.microsoft.com/.NetConfiguration/v2.0”,“sectionGroup”)

但您要求提供名称为

的元素

(“”,“sectionGroup”)

这就是处理器为您创建的内容。当序列化时,这会导致输出命名空间undeclaration xmlns =“”,以确保该元素不在命名空间中。

修复是在正确的命名空间中创建您的元素,您可以这样做,例如,通过在文字结果元素上放置命名空间声明。

答案 2 :(得分:1)

首先,如果ASP.NET仅仅因为xmlns="" pseudoattribute的存在而感到沮丧(而不是因为你的内容位于错误的命名空间而感到沮丧),那么这就是ASP.NET中的一个错误等待修复。如果您的ELMAH内容实际上位于错误的命名空间中,那么当然应该修复该问题(但是AFAICT, ELMAH config content should be in no namespace,所以你的内容很好)。

将exclude-result-prefixes属性添加到<xsl:stylesheet>开始标记可能会有所帮助:

exclude-result-prefixes="con"

至少应该从输出中删除xmlns:con="..."声明。有关详细信息,请参阅here

但是,由于您在名称空间中的某些.NetConfiguration XML下嵌入了ELMAH XML(它没有名称空间);如果XSLT决定对后者使用默认命名空间,那么除了在<sectionGroup>元素上使用某种命名空间声明之外别无选择...否则<sectionGroup>元素将在.NetConfiguration命名空间。

您尚未向我们展示输出XML的<con:configSections>部分...这有助于诊断原因并找到解决方案。特别是,您的输出XML是<con:configSections>(即使用con前缀)还是<configSections>(使用默认命名空间)?

答案 3 :(得分:-1)

名称空间声明具有以下语法。 xmlns:prefix =“ URI”

<root>

<h:table xmlns:h="http://www.w3.org/TR/html4/">
  <h:tr>
    <h:td>Apples</h:td>
    <h:td>Bananas</h:td>
  </h:tr>
</h:table>

<f:table xmlns:f="https://www.w3schools.com/furniture">
  <f:name>African Coffee Table</f:name>
  <f:width>80</f:width>
  <f:length>120</f:length>
</f:table>

</root>

源:w3schools