Определить, содержит ли файл XML определенное пространство имен - PullRequest
1 голос
/ 01 октября 2010

Опять простая вещь. У меня есть таблица стилей, которая анализирует файлы XML и XSL. По сути, он пытается определить, является ли XML таблицей стилей с:

<xsl:if test="count(//xsl:template)!=0">

Он действительно обнаруживает таблицы стилей. Однако возникают проблемы с файлами XML, которые приводят к ошибке « Неопределенный префикс пространства имен -« xsl »». (В XmlSpy. Подобные ошибки в проекте, над которым я работаю.)

Я делаю что-то не так. Любые предложения о том, как улучшить эту таблицу стилей?


Некоторая дополнительная информация: это таблица стилей, предназначенная для анализа других файлов XML, независимо от того, что они содержат. Он должен быть в состоянии преобразовать себя даже, и делает это хорошо. Также нет проблем с преобразованием других (нормальных) таблиц стилей. Проблема возникает, когда я пытаюсь преобразовать обычный файл XML. Но не все XML-файлы ...


Как оказалось, ошибка в другом. XML-файлы, которые я пытался преобразовать, содержат инструкцию обработки. Вот эта: <?xml-stylesheet href="..\MyStylesheet.xsl" type="text/xsl"?>
Проблема, с которой я столкнулся сейчас, заключается в том, что при обработке XML-файла, содержащего этот PI, XSLT начинает сообщать об ошибке с неопределенным префиксом пространства имен. Итак, как мне сказать процессору XSLT игнорировать эту инструкцию обработки?

Ответы [ 3 ]

1 голос
/ 01 октября 2010

Неправильно полагать, что файл кода XSLT всегда содержит <xsl:template> инструкцию .

Существуют примеры модулей таблицы стилей XSLT, в которых файл содержит только инструкцию <xsl:stylesheet> и одну или несколько переменных глобального уровня.Такой модуль таблицы стилей обычно импортируется / включается в другой модуль таблицы стилей с использованием инструкции <xsl:import> или <xsl:include>.

Кроме того, то, что определяет XSLT, не является префиксом элементов, составляющих инструкции XSLT .Этот префикс не обязательно должен быть "xsl", и некоторые программисты используют разные префиксы, такие как "xslt" или "x".

Что действительно определяет код XSLT, так это пространство имен XSLT .

Наконец, файл кода XSLT не гарантированно даже содержит директиву <xsl:stylesheet> , поскольку XSLT предлагает синоним: <xsl:transform>.

С учетом всехИз этих соображений лучшим тестом будет:

/*[contains('|stylesheet|transform|', concat('|', local-name(), '|')
          and
            namespace-uri()="http://www.w3.org/1999/XSL/Transform"
           )

Поскольку существует возможность наличия встроенных таблиц стилей , тест, приведенный выше, можетбыть немного изменены, чтобы покрыть их также:

//*[contains('|stylesheet|transform|', concat('|', local-name(), '|')
          and
            namespace-uri()="http://www.w3.org/1999/XSL/Transform"
           )
1 голос
/ 01 октября 2010

Дважды проверьте, как вы объявили пространство имен xsl и какой префикс пространства имен вы выбрали.

Вы должны убедиться, что префикс xsl пространства имен определен в вашей таблице стилей, если вы хотите использовать его в выражениях XPATH. Вы получите эту ошибку, если попытаетесь использовать префикс пространства имен, который не был объявлен.

Если он не объявлен где-либо далее в таблице стилей (как правило, в элементе документа, например: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">), или если вы выбрали другой префикс пространства имен (например, объявили его как " xslt * 1013" * "вот так: xmlns:xslt="http://www.w3.org/1999/XSL/Transform"), тогда, когда вы попытаетесь сослаться на" xsl", он не будет знать, на что вы ссылаетесь.

Вы можете объявить префикс xsl пространства имен в своем операторе if как быстрый тест:

<xsl:if test="count(//xsl:template)!=0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

Любые предложения о том, как улучшить это таблицы стилей?

Вы можете упростить условие теста, выбрав xsl:template элементы, вместо того, чтобы оценивать count() из них. Результаты test="//xsl:template" будут оцениваться как true(), если что-то выбрано, и false(), если ничего не выбрано.

В таблицах стилей xsl:template - это конструкции верхнего уровня, являющиеся дочерними элементами элемента документа. Вместо использования // для прохода через каждый узел в дереве XML-документа вы можете использовать более эффективное выражение XPATH:

<xsl:if test="/*/xsl:template" />
0 голосов
/ 15 октября 2010

Зачем вам нужно проверять что-либо, кроме "/ xsl: template | xsl: transform"? Они должны быть на верхнем уровне и могут только быть на верхнем уровне.

...