Остановка XSLT, включая атрибут xmlns, при добавлении элементов в файл XML

Справочная информация: я пытаюсь создать сценарий конфигурации 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 не добавлять атрибут xmls в результирующий XML?

Заранее спасибо.


Сообщения об ошибках

Для информации вот сообщения об ошибках, которые ASP/IIS дает нам:

  • Когда корневой элемент файла конфигурации (или любой другой элемент в этом отношении) имеет определение префикса xmlns:con="http://schemas.microsoft.com/.NetConfiguration/v2.0"Я получаю следующее в YSOD

    Ошибка конфигурации

    Описание: во время обработки файла конфигурации, необходимого для обслуживания этого запроса, произошла ошибка. Пожалуйста, просмотрите подробности конкретной ошибки ниже и измените файл конфигурации соответствующим образом.

    Сообщение об ошибке синтаксического анализатора: нераспознанный атрибут "xmlns:con". Обратите внимание, что имена атрибутов чувствительны к регистру.

  • Когда любой другой элемент имеет атрибут атрибута "xmlns", я получаю следующее сообщение в YSOD.

    Сообщение об ошибке синтаксического анализатора: нераспознанный атрибут "xmlns". Обратите внимание, что имена атрибутов чувствительны к регистру.

  • В других ситуациях (когда я еще не разобрался) я не получаю YSOD, а просто 500 страниц по умолчанию от IIS. Несмотря на включение отслеживания невыполненных запросов, я не получаю журналы. Это, вероятно, 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 лишним?). В любом случае, парсер конфигурации 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"
>

Еще раз спасибо за помощь всем

3 ответа

Решение

Во-первых, если ASP.NET расстроен просто наличием xmlns="" псевдоатрибут (в отличие от расстройства, потому что ваш контент находится в неправильном пространстве имен), тогда это ошибка в ASP.NET и должна быть исправлена. Если ваш контент ELMAH на самом деле находится в неправильном пространстве имен, то, конечно, эта проблема должна быть решена (но AFAICT, содержимое конфигурации ELMAH не должно быть в пространстве имен, так что у вас все в порядке).

Это может помочь добавить атрибут exclude-result-prefixes к вашему <xsl:stylesheet> начальный тег:

exclude-result-prefixes="con"

Это должно, по крайней мере, удалить xmlns:con="..." декларация из вашего вывода. Смотрите здесь для получения дополнительной информации.

Однако, так как вы встраиваете ELMAH XML (который не находится в пространстве имен) в некоторый.NetConfiguration XML, который находится в пространстве имен; если XSLT решил использовать пространство имен по умолчанию для последнего, то у него нет другого выбора, кроме как использовать какое-то объявление пространства имен в <sectionGroup> элемент... в противном случае <sectionGroup> элемент будет в пространстве имен.NetConfiguration.

Вы не показали нам <con:configSections> часть вашего выходного XML... которая будет полезна при диагностике причины и поиске решения. В частности, имеет ли ваш выходной XML <con:configSections> (т.е. используя con префикс) или <configSections> (используя пространство имен по умолчанию)?

В вашем шаблоне относительно 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"

В модели данных XSLT объявления и необъявления пространства имен не являются узлами атрибутов. Не думайте об объявлениях и объявлениях пространства имен: вместо этого думайте об именах ваших элементов. Вы хотите элемент, имя которого (используя обозначение (uri, local))

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

но вы попросили элемент, имя которого

("", "sectionGroup")

и это то, что процессор создал для вас. Когда это сериализуется, это приводит к выводу пространства имен undeclaration xmlns="", чтобы гарантировать, что элемент не находится в пространстве имен.

Исправление заключается в создании вашего элемента в правильном пространстве имен, что вы можете сделать, например, поместив объявление пространства имен в буквальный элемент результата.

Объявление пространства имен имеет следующий синтаксис. 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

Другие вопросы по тегам