Главное, что нужно понять, это то, что ваша таблица стилей диктует имя каждого элемента, который вы добавляете в дерево результатов. Имя элемента состоит из двух частей: локального имени и URI пространства имен. В приведенном выше коде вы предоставляете локальное имя (значение $xmlElem
), но не указываете URI пространства имен, что означает, что по умолчанию будет использоваться пустая строка. (На самом деле, он принимает пространство имен по умолчанию этого модуля таблицы стилей; поскольку его нет, то это пустая строка.) Другими словами, элемент будет , а не в пространстве имен . При сериализации документа процессор XSLT должен включать в себя xmlns=""
un-декларации, чтобы не объявлять пространство имен по умолчанию, отображаемое вверху. В противном случае элемент получит это пространство имен, что не соответствует вашей таблице стилей. Наименее навязчивый способ исправить это - добавить еще один параметр (например, $namespaceURI
), так же, как вы используете $xmlElem
. Тогда вы бы написали:
<xsl:element name="{$xmlElem}" namespace="{$namespaceURI}">
Теперь результирующий элемент получит любое пространство имен, которое вы указали для него (что приведет к удалению этих объявлений пространства имен по умолчанию).
Это должно ответить на ваш вопрос. В качестве бесплатного бонусного материала я предлагаю следующее. ; -)
Вы должны удалить тест узла text()
в своем сравнении значений. Очень редко вам нужно будет напрямую сравнивать значения текстовых узлов. Вместо этого вы можете просто сравнить строковое значение самого элемента (который определяется как объединение строковых значений всех его текстовых узлов-потомков). Это будет выглядеть так:
<xsl:when test="/databean/data[@id='pkhfeed']/value = '200'">
Преимущество такого способа состоит в том, что ваш код не сломается, если там будет скрыт комментарий:
<value>2<!--test-->00</value>
В этом случае есть два текстовых узла («2» и «00»). Ваш первоначальный тест не пройден, так как он проверяет, равен ли какой-либо из них «200». Маловероятно, что в этом случае это произойдет, но в любом случае проверка строкового значения элемента (в отличие от дочерних элементов его текстового узла) является хорошей практикой, когда вы этого намерены.
Наконец, я призываю вас ознакомиться с правилами шаблонов и контекстом XPath. Я стараюсь избегать <xsl:choose>
, <xsl:call-template>
и <xsl:with-param>
, когда это возможно. С одной стороны, шаблонные правила могут помочь вам избежать многих уродливых, многословных частей XSLT.
<xsl:template match="/databean[data[@id='pkhfeed']/value = '200']" priority="1">
<StructureA xmlns="http://...">
...
</StructureA>
</xsl:template>
<xsl:template match="/databean">
<StructureB xmlns="http://...">
...
</StructureB>
</xsl:template>
Даже если вы продолжаете использовать <xsl:call-template>
, вам не нужно передавать этот параметр $structure
, так как текущий узел останется неизменным в вызываемом шаблоне. Вы можете также легко получить доступ к //databean
(или /databean
, что, как я подозреваю, то, что вы имеете в виду) из любого из ваших шаблонов StructureA
или StructureB
, поскольку текущий узел все равно будет "/" (документ узел).
Если вы хотите узнать больше о базовой модели обработки XSLT и ее наиболее мощных функциях (правилах шаблонов), тогда я советую вам ознакомиться с «Как работает XSLT» , глава с бесплатным примером из моего XSLT 1.0 Pocket Reference .
Надеюсь, это было полезно для вас, даже если это больше, чем вы рассчитывали!