Сопоставить префиксы входного документа XSLT с предпочтительными значениями - PullRequest
2 голосов
/ 22 июля 2010

Используя XSLT, мне интересно, как заставить вывод использовать префиксы пространства имен моей таблицы стилей, а не префиксы входного документа. В качестве примера приведем этот очень упрощенный документ:

<?xml version="1.0"?>
<a:node xmlns:a="urn:schemas:blah:"/>

И следующее XSL-преобразование:

<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:blah="urn:schemas:blah:" version="2.0">
   <xsl:output indent="yes">
   <xsl:template match="/blah:node">
      <xsl:copy/><!-- marked -->
   </xsl:template>
</xsl:transform>

Я могу сказать, что процессор (Saxon8, если это имеет значение) распознает эквивалентность префиксов 'blah:' и 'a:', но fn: in-scope-prefixes () , например, не не показывать «бла», только «а». Изменение строки <!-- marked --> выше на:

<node><xsl:value-of select="in-scope-prefixes(.)"/></node>

Выходы:

<?xml version="1.0" encoding="UTF-8"?>
<node xmlns:blah="urn:schemas:blah:">xml a</node>

Как можно сопоставить префикс ввода «а» с «бла», не зная заранее, что входной файл вызывает этот префикс «а»? (Так что <xsl:namespace-alias/> не будет работать для меня.)

В качестве дальнейшего контекста, если он указывает на лучшее решение, это для просмотра документов XML, которые генерируются извне. Внешний процесс создает входной документ, используя автоматически сгенерированные префиксы «a:», «b:», «c:» и т. Д. Я хочу иметь возможность отображать эти префиксы с использованием префиксов пространства имен «Friendlier».

Обновление : поведение in-scope-prefixes () объясняется определением статически известных пространств имен

Ответы [ 3 ]

3 голосов
/ 22 июля 2010

Это преобразование ( в XSLT 1.0 и XSLT 2.0 (просто измените атрибут version)):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my"
 >
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <my:namespaces>
    <ns prefix="blah" uri="urn:schemas:blah:"/>
    <ns prefix="foo" uri="uff:anotherNamespace"/>
  </my:namespaces>

  <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match=
 "*[namespace-uri()=document('')/*/my:namespaces/*/@uri]">
  <xsl:variable name="vNS" select=
  "document('')/*/my:namespaces/*
                   [@uri=namespace-uri(current())]"/>
  <xsl:element name="{$vNS/@prefix}:{local-name()}"
       namespace="{namespace-uri()}">
   <xsl:copy-of select=
    "namespace::*[not(. = namespace-uri(current()))]"/>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

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

при применении к этому документу XML :

<t>
    <a:node xmlns:a="urn:schemas:blah:"/>
    <b:node xmlns:b="urn:schemas:blah:"/>
    <c:node xmlns:c="uff:anotherNamespace"/>
</t>

требуемыйрезультат получается :

<t>
   <blah:node xmlns:blah="urn:schemas:blah:"/>
   <blah:node xmlns:blah="urn:schemas:blah:"/>
   <foo:node xmlns:foo="uff:anotherNamespace"/>
</t>
1 голос
/ 22 июля 2010

Как насчет преобразования идентификаторов плюс этот шаблон:

<xsl:template match="blah:*">
  <xsl:element name="blah:{local-name()}">
    <xsl:apply-templates select="*|@*" />
  </xsl:element>
</xsl:template>

Я не уверен, что это самый элегантный способ сделать это в XSLT 2.0, но он работает.

0 голосов
/ 22 июля 2010

Посмотрите на спецификацию для элемента верхнего уровня <xsl:namespace-alias ...>.Я верю, что это сделает то, что вы хотите.

...