将元素添加到 XML 文件时停止包含 xmlns 属性的 XSLT

发布于 2024-12-19 23:16:43 字数 4170 浏览 2 评论 0原文

背景:我正在尝试编写 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 向我们提供的错误消息: -

  • 当配置文件的根元素(或与此相关的任何其他元素)具有前缀定义 < code>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 不是多余的吗?)。不管怎样,配置解析器在存在 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"
>

再次感谢大家的帮助

Background: I am trying to script the configuration of Elmah so that, in production, I can run a script that will copy binaries and edit web.config file accordingly.

I decided to use XSLT to make the alterations to the web.config file. To start with I want to add a sectionGroup in the configSections element like so.

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

Here is my XSLT template

<?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>

And it almost does what I want. It generates the following 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-->

Note the xmlns attribute. The presence of this attribute really upsets ASP.Net (even though it is perfectly valid XML - albeit superfluous) and all requests result in a HTTP 500 error (see the section below for the error message). The only error message that I could get out of

Removing the xmlns attribute fixes this problem.

I could use xsl:element to generate the new XML but this leads to very verbose and hard to read XSL.

So my question is how to tell XSLT not to add the xmls attribute in the resulting XML?

Thanks in advance.


The error messages

For information here are the error messages that ASP/IIS gives us: -

  • When the root element of the config file (or any other element for that matter) has the prefix definition xmlns:con="http://schemas.microsoft.com/.NetConfiguration/v2.0", I get the following in a YSOD

    Configuration Error

    Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

    Parser Error Message: Unrecognized attribute 'xmlns:con'. Note that attribute names are case-sensitive.

  • When any other element has 'xmlns' attribute attribute, I get the following message in a YSOD.

    Parser Error Message: Unrecognized attribute 'xmlns'. Note that attribute names are case-sensitive.

  • In other situations (I have not yet worked out when) I son't get a YSOD but just a default 500 page from IIS. Despite enabling failed request tracing, I get no logs. This is probably PEBKAC though.


The solution to my problem

Thanks to LarsH, Vincent Biragnet and Michael Kay for their responses, which between them have sorted out my problem.

Firstly - my XSLT as posted is wrong, as Michael and Vincent point out, the sectionGroup element should be in the namespace "http://schemas.microsoft.com/.NetConfiguration/v2.0".

To sort this, I defined the default namespace in my XSLT like so xmlns="http://schemas...".

But (why I do not know) the sectionGroup element is then output as

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

(Isn't the xmlns:con superfluous?). Anyway, the configuration parser barfs at the presence of xmlns:con.

But LarsH to the rescue - his suggestion suggestion of using exclude-result-prefixes="msxsl con" gets rid of those pesky things.

So the top of my (now working) XSLT now looks like this

<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"
>

Thanks again for everyone's help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

吹梦到西洲 2024-12-26 23:16:43

首先,如果 ASP.NET 仅仅因为 xmlns="" 伪属性的存在而感到不安(而不是因为内容位于错误的命名空间中而感到不安),那么这就是 ASP 中的错误。 NET 并且应该被修复。如果您的 ELMAH 内容实际上位于错误的命名空间中,那么当然应该修复该问题(但是 AFAICT,ELMAH 配置内容应该不在命名空间中,所以你的没问题)。

将 except-result-prefixes 属性添加到 开始标记可能会有所帮助:

exclude-result-prefixes="con"

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

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

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

First, if ASP.NET is upset merely by the presence of the xmlns="" pseudoattribute (as opposed to being upset because your content is in the wrong namespace), then that is a bug in ASP.NET and ought to be fixed. If your ELMAH content actually is in the wrong namespace, then of course that issue should be fixed (but AFAICT, ELMAH config content should be in no namespace, so yours is fine).

It may help to add the exclude-result-prefixes attribute to your <xsl:stylesheet> start tag:

exclude-result-prefixes="con"

That should at least remove the xmlns:con="..." declaration from your output. See here for more info.

However, since you are embedding the ELMAH XML (which is in no namespace) under some .NetConfiguration XML, which is in a namespace; if XSLT has decided to use the default namespace for the latter, then it has no choice but to use some sort of namespace declaration on the <sectionGroup> element... otherwise the the <sectionGroup> element will be in the .NetConfiguration namespace.

You haven't shown us the <con:configSections> part of your output XML... that would be helpful in diagnosing the cause, and finding a solution. In particular, does your output XML have <con:configSections> (i.e. using the con prefix) or <configSections> (using the default namespace)?

丘比特射中我 2024-12-26 23:16:43

在涉及 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 ”

In your template concerning the con:configSections element, you add a sectionGroup element that is not qualified, no namespace is linked with it.

Try to replace the sectionGroup part with that :

  <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>

If assume that sectionGroup has to be in the same namespace than configSection.

Another alternative is to keep your code without prefix and to add the following namespace declaration in the sectionGroup tag : xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"

画中仙 2024-12-26 23:16:43

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

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

的元素,但您要求的元素名称是

("", "sectionGroup")

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

解决方法是在正确的命名空间中创建元素,例如,可以通过在文字结果元素上放置命名空间声明来执行此操作。

In the XSLT data model, namespace declarations and undeclarations are not attribute nodes. Don't think about namespace declarations and undeclarations: instead think about the names of your elements. You want an element whose name (using the notation (uri, local)) is

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

but you have asked for an element whose name is

("", "sectionGroup")

and this is what the processor has created for you. When this is serialized, this results in the namespace undeclaration xmlns="" being output in order to ensure that the element is in no namespace.

The fix is to create your element in the right namespace, which you can do, for example, by putting a namespace declaration on the literal result element.

臻嫒无言 2024-12-26 23:16:43

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

The namespace declaration has the following syntax. 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>

source : w3schools

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文