2010-07-21 1 views
2

Использование XSLT, мне интересно, как получить вывод, чтобы использовать префиксы пространства имен стилей, а не префиксы входного документа. В качестве примера, учитывая это очень упрощенный документ:Карта 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(), например, не показывает' blah ', только' a '. Изменение <!-- 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> 

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

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

Обновление: Поведение в области видимости-префиксов() объясняется the definition of Statically known namespaces

+0

Хороший вопрос (+1). См. Мой ответ для полного решения XSLT 1.0 и XSLT 2.0. –

ответ

3

Это преобразование (как в 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> 
+0

Очень приятно. Легко добавлять пары пространства имен + префикс, а неизменные префиксы легко передаются через as-is. – benizi

+0

Хорошее решение, как всегда. – Tomalak

0

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

+0

Спецификация, о которой я конкретно упомянул, не будет работать. :-) Я снова посмотрел. Похоже, что он работает с именами префиксов, а не с URI пространства имен. Итак, тот факт, что «urn: schemas: blah:» есть «a:» за один проход внешнего процесса, а «b:» в другом прогоне мешает ему работать здесь, правильно? – benizi

1

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

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

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

+0

Похоже, что это закончит работать для меня (используя это как первый проход для очистки имен префикса, а затем используя мой старый XSLT как второй). Есть ли хороший способ получить пространства имен, объявленные в корневом элементе? Как бы то ни было, если у меня есть , узлы пространства имен присоединяются к , а не к . – benizi

 Смежные вопросы

  • Нет связанных вопросов^_^