XSLT: добавить пространство имен к корневому элементу - PullRequest
7 голосов
/ 22 апреля 2010

Мне нужно изменить пространства имен в корневом элементе следующим образом:

входной документ:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
xmlns:ns2="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-22-9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

желаемый вывод:

<foo audience="external" xsi:schemaLocation="urn:isbn:1-931666-22-9
     http://www.loc.gov/ead/ead.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
    instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-22-9">

Я пытался сделать это, копируя весь документ и прежде чем давать какие-либо другие инструкции по преобразованию, но следующее не работает:

<xsl:template match="* | processing-instruction() | comment()">
    <xsl:copy copy-namespaces="no">
        <xsl:for-each select=".">
            <xsl:attribute name="audience" select="'external'"/>
            <xsl:namespace name="xlink" select="'http://www.w3.org/1999/xlink'"/>
        </xsl:for-each>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

Спасибо за любой совет!

Ответы [ 2 ]

10 голосов
/ 23 апреля 2010

XSLT 2.0 не требуется для решения этой проблемы.

Вот решение XSLT 1.0 , которое работает так же хорошо, как XSLT 2.0 (просто изменитеversion атрибут 2.0):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 exclude-result-prefixes="xlink"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="/*">
   <xsl:element name="{name()}" namespace="{namespace-uri()}">

      <xsl:copy-of select=
        "namespace::*
           [not(name()='ns2')
          and
            not(name()='')
           ]"/>

      <xsl:copy-of select=
       "document('')/*/namespace::*[name()='xlink']"/>

      <xsl:copy-of select="@*"/>

      <xsl:attribute name="audience">external</xsl:attribute>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

Когда вышеуказанное преобразование применяется к этому XML-документу :

<foo
xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
xmlns:ns2="http://www.w3.org/1999/xlink"
xmlns="urn:isbn:1-931666-22-9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>

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

<foo xmlns="urn:isbn:1-931666-22-9"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
     audience="external"/>
1 голос
/ 15 октября 2010

Вы действительно должны использовать для этого «шаблон личности», и вы всегда должны иметь его под рукой. Создайте XSLT с этим шаблоном, назовите его «identity.xslt», затем в текущий XSLT. Предположим, префикс «плохой» для пространства имен, которое вы хотите заменить, и «хороший» для того, который вы хотите заменить на , тогда все, что вам нужно, это такой шаблон (я на работе, так что простите за форматирование; я вернусь к этому, когда буду дома): ... Если это не сработает в XSLT 1.0, используйте выражение соответствия, например "* [namespace-uri () = 'urn: bad-namespace '"и следуйте инструкциям Dimitre для программного создания нового элемента. Внутри вам действительно нужно просто рекурсивно применить шаблон ... но на самом деле, прочитайте шаблон идентичности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...