Остановка 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