XSL: игнорирование / удаление пространств имен во вторичных документах - PullRequest
1 голос
/ 12 января 2010

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

<toplevel xmlns:foo1="http://foo1">
 <path xmlns="http://foo1">
   <mytag>bar</mytag>
  </path>
</toplevel>

В XSL я делаю это:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:foo1="http://foo1"
 exclude-result-prefixes="foo1">
  <xsl:variable name="secondary1" select="document('secondary1.xml')/toplevel"/>
  <foo>
    <xsl:value-of select="$secondary1//foo1:path/foo1:mytag"/>
  </foo>
</xsl:stylesheet>

С большим количеством вторичных источников, каждый из которых использует свое пространство имен, префикс каждого отдельного тега утомителен, и такое повторение не может быть правильным в любом случае. Есть ли способ использовать document () так, чтобы пространство имен импортированного набора узлов было удалено (или для достижения того же эффекта другим способом)?

Ответы [ 2 ]

3 голосов
/ 12 января 2010

В XPath / XSLT 1.0, чтобы выбрать элемент, соответствующий пространству имен, по имени, вы должны использовать префикс. В XSLT 2.0 вы можете использовать функцию xpath-default-namespace, которая позволяет вам устанавливать пространство имен по умолчанию для выражений XPath, поэтому вам больше не нужно использовать префиксы. См. XSLT 2.0: xpath-default-namespace для получения дополнительной информации. Вы можете использовать этот атрибут в любом элементе таблицы стилей, и он вступает в силу для всех элементов-потомков, если они не переопределены. (Определите его с помощью xsl: если вы хотите поместить его в элемент, отличный от XSLT, то есть в буквальный элемент результата.)

В XPath 1.0 вы также можете довольно неуклюже выбирать элементы по локальному имени, используя, например, *[local-name() = 'path']/*[local-name() = 'mytag']. В XPath 2.0 для большей краткости вы можете использовать подстановочные знаки пространства имен, как в *:path/*:mytag, , как описано здесь . Это было несколько спорным дополнение, так как кажется, поощрять и / или оправдать такое же сомнительное использование пространств имен, что система, по-видимому занято.

2 голосов
/ 12 января 2010

По сути, узел с пространством имен - это совершенно другое животное , чем узел с другим пространством имен - даже если они имеют одно и то же локальное имя. (Это во многом аналогично тому, как пространства имен работают везде - на самом деле нет простого способа «игнорировать» пространства имен. Подумайте об игнорировании пространств имен при обращении к классам в C #.)

Чистым подходом было бы упомянуть каждое пространство имен, с которым вы можете столкнуться в XSLT, и работать с префиксами, даже если оно кажется повторяющимся.

Не очень чистый способ таков:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:variable name="secondary1" select="document('secondary1.xml')"/>

  <xsl:template match="/">
    <foo source="1">
      <xsl:value-of select="
        $secondary1//*[local-name() = 'path']/*[local-name() = 'mytag']
      "/>
    </foo>
  </xsl:template>
</xsl:stylesheet>

Это на самом деле не более приятно для глаз, чем работа с префиксами, оно длиннее и сложнее для чтения, оно неоднозначно и, наконец, что не менее важно, - медленнее, потому что движок должен тестировать предикат на каждый шаг в XPath. Выбирай.

...