使用XSLT添加其他名称空间 [英] Add additional namespace with XSLT

查看:91
本文介绍了使用XSLT添加其他名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仅在不存在特定元素的情况下,我才需要向已命名空间的XML文件添加一个额外的命名空间.

I need to add an additional namespace to an already namespaced XML file but only if a particular element does not exist.

我的XML文档如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp">
    <common>Stuff Here</common>
    <ns2:person id="123">
        <ns3:firstname>Billy</ns3:firstname>
        <ns2:lastname>Bobby</ns2:lastname>
    </ns2:person>
</everyone>

...,并且如果person元素中没有ns3:firstname元素,我想添加一个新的名称空间和(例如xmlns:frog ="FFF"),以及person中的另一个元素,如下所示:

... and if there is no ns3:firstname element in the person element, I'd like to add a new namespace and (e.g. xmlns:frog="FFF") and also an additional element within person as shown below:

所需的输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" xmlns:frog="FFF" company="TestingCorp">
    <common>Stuff Here</common>
    <ns2:person id="123">
        <frog:title>
            <Master/>
        </frog:title>
        <ns2:lastname>Bobby</ns2:lastname>
    </ns2:person>
</everyone>

我的XSL文档当前为:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

  <xsl:template match="/*">
    <xsl:element name="ns:{local-name()}">
        <xsl:attribute name="frog">fff</xsl:attribute>
        <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

....不幸的是,这不起作用.

.... unfortunately this does not work.

我已经尝试了许多不同的方法,但是似乎无法使用XSLT v1.0来实现.任何帮助将不胜感激.

I've tried lots of different things but can't seem to achieve this using XSLT v1.0. Any help would be greatly appreciated.

推荐答案

首先,您需要在样式表中声明各种名称空间,以及"AAA"默认名称空间

First you need to declare the various namespaces in your stylesheet, as well as the "AAA" default namespace

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="AAA"
    xmlns:frog="FFF"
    xmlns:ns2="BBB"
    xmlns:ns3="CCC">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

  <!-- for a Person with no firstname, add a frog:title -->
  <xsl:template match="ns2:person[not(ns3:firstname)]">
      <xsl:copy>
          <!-- must handle attributes before elements/text nodes -->
          <xsl:apply-templates select="@*" />
          <frog:title>
              <Master/>
          </frog:title>
          <xsl:apply-templates select="node()" />
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

这将产生

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp">
    <common>Stuff Here</common>
    <ns2:person id="123">
        <frog:title xmlns:frog="FFF">
            <Master/>
        </frog:title>
        <ns2:lastname>Bobby</ns2:lastname>
    </ns2:person>
</everyone>

如果xmlns:frog绝对必须位于everyone元素上而不是每个frog:title上,则可以添加另一个模板

If the xmlns:frog absolutely must be on the everyone element rather than on each frog:title then you could add another template

<xsl:template match="/*">
  <xsl:copy>
    <xsl:copy-of select="document('')/xsl:stylesheet/namespace::frog" />
    <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
</xsl:template>

从样式表元素中复制名称空间声明(尽管这意味着每个输出文档都具有xmlns:frog声明,即使它不涉及任何frog:*元素也是如此).

to copy the namespace declaration off the stylesheet element (though this would mean that every output document has an xmlns:frog declaration even if it doesn't involve any frog:* elements).

显然,Xalan不喜欢document('')中的copy-of命名空间,如果您知道文档元素将始终具有相同的名称,则可以将其硬编码为文字结果元素

apparently Xalan doesn't like the copy-of namespaces from document(''), as an alternative, if you know that the document element will always have the same name then you can hard code that as a literal result element

<xsl:template match="/*">
  <everyone xmlns:frog="FFF">
    <xsl:copy-of select="namespace::*" />
    <xsl:apply-templates select="@*|node()" />
  </everyone>
</xsl:template>

(从技术上讲,即使没有此模板中的显式xmlns:frog,它也可以执行您想要的操作,因为文字结果元素始终会获得样式表中范围内的命名空间声明.已声明,但如果包含此意图,则可以说清楚了

(technically it will do what you want even without the explicit xmlns:frog in this template, since literal result elements always get the namespace declarations that are in scope at the point in the stylesheet where they are declared, but the intention is arguably clearer if you include it)

此邮件列表帖子提供了一些可能的原因见解导致document('')无法正常工作.

This mailing list post gives some possible insights into the reason for document('') not working as it should.

这篇关于使用XSLT添加其他名称空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆