Остановка XSLT, включая атрибут xmlns, при добавлении элементов в файл XML - PullRequest
1 голос
/ 06 декабря 2011

Справочная информация: я пытаюсь создать сценарий конфигурации 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, Винсенту Бирагну и Майклу Кей за их ответы, которые между ними решили мою проблему.

Во-первых, мой 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 ]

1 голос
/ 06 декабря 2011

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

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

, но вы запросили элемент с именем

("", "sectionGroup")

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

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

1 голос
/ 06 декабря 2011

Во-первых, если 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> (с использованием пространства имен по умолчанию)?

1 голос
/ 06 декабря 2011

В вашем шаблоне, касающемся элемента 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"

...