【问题标题】:Stopping XSLT including xmlns attribute when adding elements to XML file向 XML 文件添加元素时停止包含 xmlns 属性的 XSLT
【发布时间】:2012-01-14 06:03:33
【问题描述】:

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

我决定使用 XSLT 来更改 web.config 文件。首先,我想像这样在configSections 元素中添加一个sectionGroup

  <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”。请注意,属性名称区分大小写。

  • 1234563尽管启用了失败的请求跟踪,但我没有收到任何日志。不过这可能是 PEBKAC。

我的问题的解决方案

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

首先 - 正如迈克尔和文森特指出的那样,我发布的 XSLT 是错误的,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 不是多余的吗?)。无论如何,配置解析器在 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"
>

再次感谢大家的帮助

【问题讨论】:

  • 您是否尝试将默认 xmlns 添加到您的 xsl:stylesheet 中?尝试添加xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"
  • +1 很好地解释了解决方案。
  • 奇怪的是 &lt;sectionGroup&gt; 应该在 .NetConfiguration 命名空间中;这意味着此处显示的配置 XML 无效:msdn.microsoft.com/en-us/library/aa479332.aspx
  • 是的 - 配置解析器似乎很乐​​意解析文件,无论是否将默认命名空间定义为“schemas.microsoft.com/.NetConfiguration/v2.0”。我刚刚意识到这对我不利 - 我刚刚编写的 XSLT 仅在元素位于 MSConfig 命名空间中时才有效。我将不得不对其进行处理,以便它可以在有或没有默认命名空间声明的情况下工作!

标签: xslt web-config elmah


【解决方案1】:

首先,如果 ASP.NET 仅仅因为 xmlns="" 伪属性的存在而感到不安(而不是因为您的内容位于错误的命名空间中而感到不安),那么这是 ASP.NET 中的一个错误,应该是固定的。如果您的 ELMAH 内容实际上位于错误的命名空间中,那么该问题当然应该得到解决(但 AFAICT, ELMAH config content should be in no namespace,所以您的没问题)。

将 exclude-result-prefixes 属性添加到您的 &lt;xsl:stylesheet&gt; 开始标签可能会有所帮助:

exclude-result-prefixes="con"

这至少应该从您的输出中删除 xmlns:con="..." 声明。请参阅here 了解更多信息。

但是,由于您将 ELMAH XML(不在命名空间中)嵌入到位于命名空间中的某些 .NetConfiguration XML 下;如果 XSLT 决定为后者使用默认命名空间,那么它别无选择,只能在 &lt;sectionGroup&gt; 元素上使用某种命名空间声明......否则 &lt;sectionGroup&gt; 元素将位于 .NetConfiguration 命名空间中。

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

【讨论】:

  • P.S.它也可能有助于查看 ASP.NET 给出的任何错误消息。如果 500 错误页面没有提供任何详细信息,请打开调试日志并检查日志文件。
  • “首先,如果 ASP.NET 仅仅因为 xmlns="" 伪属性的存在而感到不安......那么这是 ASP.NET 中的一个错误,应该修复” - 我不能更同意。我的一位同事在做不同的事情时遇到了同样的问题。
【解决方案2】:

在有关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"

【讨论】:

  • 我认为您不能假设 sectionGroup 应该与 configSection 在同一个命名空间中。相反,查看msdn.microsoft.com/en-us/library/aa479332.aspx,似乎&lt;sectionGroup&gt; 应该不在命名空间中。但是我没有使用 ELMAH 的经验,所以如果我错了,请有人纠正我。
【解决方案3】:

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

的元素

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

但您要求的元素名称为

("", "sectionGroup")

这就是处理器为您创建的。当它被序列化时,这将导致命名空间未声明 xmlns="" 被输出,以确保该元素不在命名空间中。

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

【讨论】:

  • Michael,你确定他想要 .NetConfiguration 命名空间中的 sectionGroup 元素吗?查看msdn.microsoft.com/en-us/library/aa479332.aspx 此处的示例,它看起来应该不在命名空间中。
  • Michael Kay 是正确的(您是我办公桌上编写 XSLT 参考的同一个 Kay 先生吗?) - sectionGroup 元素应该位于 MS config 命名空间中。这是我原来的 XSLT 中的一个错误。感谢您指出这一点。
  • @ChrisF:是的,同样的凯先生。 :-)
【解决方案4】:

命名空间声明具有以下语法。 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    • 1970-01-01
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多