XSLT: Add namespace to root element

拜拜、爱过 提交于 2019-12-28 13:36:45

问题


I need to change namespaces in the root element as follows:

input document:

<?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">

desired output:

<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">

I was trying to do it as I copy over the whole document and before I give any other transformation instructions, but the following doesn't work:

<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>

Thanks for any advice!


回答1:


XSLT 2.0 isn't necessary to solve this problem.

Here is an XSLT 1.0 solution, which works equally well as XSLT 2.0 (just change the version attribute to 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>

When the above transformation is applied on this XML document:

<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"/>

the wanted result is produced:

<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"/>



回答2:


You should really be using the "identity template" for this, and you should always have it on hand. Create an XSLT with that template, call it "identity.xslt", then into the current XSLT. Assume the prefix "bad" for the namespace you want to replace, and "good" for the one you want to replace it with, then all you need is a template like this (I'm at work, so forgive the formatting; I'll get back to this when I'm at home): ... If that doesn't work in XSLT 1.0, use a match expression like "*[namespace-uri() = 'urn:bad-namespace'", and follow Dimitre's instructions for creating a new element programmatically. Within , you really need to just apply-template recursively...but really, read up on the identity template.



来源:https://stackoverflow.com/questions/2686650/xslt-add-namespace-to-root-element

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!