Набор узлов XSL: не находить дочерние элементы по имени

Я новичок в xsl, поэтому, возможно, это очень простой вопрос. У меня есть файл xsl, в котором я хочу найти конкретное значение, определенное в параметре-объекте:

<xsl:param name = "locales">
    <label name = "testname"><locale name = "de">german text</locale><locale name = "en">english text</locale></label>
</xsl:param>

<xsl:template match = "foo">
    <topLevelElement xmlns = "http://foo.bar.org">
        <xsl:value-of select = "ext:node-set($locales)/label[@name='testname']/locale[@name='en']"/>
    </topLevelElement>
</xsl:template>

Я ожидал получить значение 'english text', потому что я хочу найти в параметре localeslabel с именем testname. Там я хочу найти locale с именем en. Но это не работает. Когда я заменяю имя конкретных элементов (метка и языковой стандарт) звездочкой, это работает:

<xsl:param name = "locales">
    <label name = "testname"><locale name = "de">german text</locale><locale name = "en">english text</locale></label>
</xsl:param>

<xsl:template match = "foo">
    <topLevelElement xmlns = "http://foo.bar.org">
        <xsl:value-of select = "ext:node-set($locales)/*[@name='testname']/*[@name='en']"/>
    </topLevelElement>
</xsl:template>

Кто-нибудь может сказать мне, почему я не могу найти ребенка по имени? Большое спасибо!

Редактировать: В коде не отображается пространство имен (я думаю, оно интерпретируется браузером). Без скобок в начале и в конце:

xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns = "http://foo.bar.org"xmlns:ext = "http://exslt.org/common" version = "1.0" xsl:output method = "xml" version = "1.0" encoding = "UTF-8"/

Дайте угадаю: в вашем XSLT-файле определено пространство имен по умолчанию xmlns = "...".

Tomalak 10.08.2018 15:49

Да. Я отредактировал свой вопрос. Так в чем проблема? У моей метки и локалей теперь есть другое пространство имен, так что я не могу их найти?

Markus 10.08.2018 15:58

Где функция замедления ext: node-set (...)?

Amrendra Kumar 10.08.2018 16:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
276
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Так что у тебя есть

<xsl:stylesheet
    xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
    xmlns = "http://foo.bar.org"
    xmlns:ext = "http://exslt.org/common"
>

и это определяет пространство имен по умолчанию. Это означает, что каждый элемент XML, создаваемый вашей программой XSLT (который явно не создается с пространством имен) будет в этом пространстве имен. Это также относится к любому элементу, который вы не выводите.

А это означает, что вы больше не можете выбирать эти элементы с помощью «простого» XPath, потому что простой XPath предполагает, что элементы не находятся в пространстве имен.

ext:node-set($locales)/label[@name='testname']/locale[@name='en']

ищет элементы <label>, которые не находятся в пространстве имен, и элементы <locale>, которые не находятся в пространстве имен. И способ сослаться на пространство имен в XPath - использовать префикс.

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

<xsl:stylesheet
    xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
    xmlns = "http://foo.bar.org"
    xmlns:foo = "http://foo.bar.org"
    xmlns:ext = "http://exslt.org/common"
>

Здесь пространство имен "http://foo.bar.org" объявлено как дефолт, но также имеет префикс foo. Теперь вы можете это сделать:

ext:node-set($locales)/foo:label[@name='testname']/foo:locale[@name='en']

И все заработает.


Лично я бы не стал использовать <xsl:param> для того, что вы делаете. Я бы создал дополнительный XML-документ без пространств имен, назвал бы его locales.xml, а затем сделал бы:

<!-- top-level -->
<xsl:variable name = "locales" select = "document('locales.xml')" />

<!-- ...later -->
<xsl:value-of select = "$locales/*/label[@name='testname']/locale[@name='en']" />

Таким образом, не требуются ни вспомогательные пространства имен, ни ext:node-set(), а также повышается модульность.

Большое спасибо за всю вашу информацию! Это мне очень помогло. Я рассмотрю ваше предложение использовать дополнительный файл XML.

Markus 10.08.2018 16:15
Ответ принят как подходящий

Один из способов исправить это без изменения XPath - изменить

<xsl:param name = "locales">
    <label name = "testname"><locale name = "de">german text</locale><locale name = "en">english text</locale></label>
</xsl:param>

к

<xsl:param name = "locales" xmlns = "">
    <label name = "testname"><locale name = "de">german text</locale><locale name = "en">english text</locale></label>
</xsl:param>

Благодарность! это простое решение, которое идеально подходит для меня!

Markus 10.08.2018 16:13

@Markus Обратите внимание и на нижнюю часть моего ответа. Для этого даже не нужны пространства имен и node-set().

Tomalak 10.08.2018 16:14

да спасибо большое томалак. Я подумаю над твоим решением. Но я новичок в xsl, поэтому для полного понимания вашего решения требуется некоторое время;) Но ваш ответ мне очень помогает.

Markus 10.08.2018 16:18

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