Я новичок в 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', потому что я хочу найти в параметре locales
label
с именем 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"/
Да. Я отредактировал свой вопрос. Так в чем проблема? У моей метки и локалей теперь есть другое пространство имен, так что я не могу их найти?
Где функция замедления ext: node-set (...)?
Так что у тебя есть
<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.
Один из способов исправить это без изменения 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 Обратите внимание и на нижнюю часть моего ответа. Для этого даже не нужны пространства имен и node-set()
.
да спасибо большое томалак. Я подумаю над твоим решением. Но я новичок в xsl, поэтому для полного понимания вашего решения требуется некоторое время;) Но ваш ответ мне очень помогает.
Дайте угадаю: в вашем XSLT-файле определено пространство имен по умолчанию
xmlns = "..."
.