如何动态设置 XSLT 转换输出 XML 的默认命名空间声明? [英] How can I dynamically set the default namespace declaration of an XSLT transformation's output XML?

查看:32
本文介绍了如何动态设置 XSLT 转换输出 XML 的默认命名空间声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以使用 <xsl:namespace>. 如果我尝试为默认命名空间执行此操作:

I can do it, but not for the default namespace, using the <xsl:namespace>. If I try to do it for the default namespace:

<xsl:namespace name="" select"myUri"/>

它永远不起作用.它要求我明确定义元素的命名空间才能使用上述空前缀声明.
我想要这个的原因是因为我有一个将输入 XML 文件转换为另一个输出 xml 的任务.输出 XML 有很多元素,我不想为每个元素显式设置命名空间.这就是为什么我想设置默认值并且不再打扰.但默认值必须根据源 XML 中的某些数据计算得出.它在整个转换过程中不会改变,但它依赖于输入的 XML 数据.有什么解决办法吗?

it never works. It demands that I explicitly define the namespace of the element to be able to use the above null prefix declaration.
The reason I want this is because I have a task to transform an input XML file to another output xml. The output XML has many elements and i dont want to have to explicitly set the namespace for every element. Thats why I want to set the default and never bother again. But the default must be computed from some data in the source XML. It does not change during the whole transformation, but it is dependent on input XML data. Any solution?

编辑 1:补充:

  1. 我想动态创建一个命名空间并将其设置为输出xml文档的默认命名空间.命名空间的 uri 源自输入 XML 中的一些数据.
  2. 如果我在根输出元素中使用 <xsl:namespace>,则无法为其创建默认命名空间,只能创建一个带前缀的命名空间.即使有前缀,它也不会传播给孩子.
  1. I want to create a namespace dynamically and set it to be the default namespace of the output xml document. The uri of the namespace is derived from some data in the input XML.
  2. If I use <xsl:namespace> in my root output element, I cannot create a default namespace for it, only a prefixed one. And even with the prefixed one, it does not propagate to children.

编辑 2:dkackman 提议:

EDIT 2: dkackman proposed:

<xsl:template match="root">
  <xsl:param name ="ns">my-computed-namespace</xsl:param>
  <xsl:element name="newRoot" namespace="{$ns}"/>
</xsl:template>

它几乎解决了问题.不幸的是,孩子们被转换器注入了 ""(blank) 命名空间.如果我放置一个子元素,我会得到以下结果:

It almost solves the problem. Unfortunately the children are injected with ""(blank) namespace by the transformer. Here is what I get if I put a child element:

<newRoot xmlns="my-computed-namespace"> 
    <child xmlns=""> ... 
    </child> 
 </newRoot>

变压器为什么要把这个 xmlns="" 放在孩子身上?如果我可以防止这种情况发生,那么我已经找到了解决方案.

Why does the transformer put this xmlns="" in the children? If I can prevent this then I have found my solution.

推荐答案

除了提供准确答案的@Tomalak 之外,请注意 不是旨在创建一个命名空间声明,供 XSLT 处理器使用,通常具有所有元素或属性.

In addition to @Tomalak who has provided the precise answer, do note that <xsl:namespace> is not intended to create a namespace declaration to be used by the XSLT processor generally with all elements or attributes.

的目的是创建一个特定的命名空间节点.这个节点只有一个有限的范围:当前元素或属性,以及当前节点的所有子节点,如果他们没有将前缀重新分配给另一个命名空间 uri.

The purpose of <xsl:namespace> is to create a specific namespace node. This node has a limited scope only: the current element or attribute, and all children of the current node, if they do not re-assign the prefix to another namespace-uri.

使用 仅当我们想为必须动态生成的命名空间 uri 动态创建命名空间时才必要(在转换开始时静态未知).这种情况极为罕见.

Using <xsl:namespace> is necessary only if we want to create a namespace dynamically for a namespace-uri that must be generated dynamically (was not known statically at the start of the transformation). Such cases are extremely rare.

在静态已知所需的 namspace-uri 的所有情况下,只需在合适的可见性级别声明此命名空间(通常在 指令),然后在必须使用此命名空间的任何地方使用关联的前缀.

In all cases when the desired namspace-uri is known statically, simply declare this namespace at a suitable level of visibility (usually at the <xsl:stylesheet> instruction) and then simply use the associated prefix, anywhere this namespace must be used.

更新:我刚刚在另一个论坛上与专家的对话中确认,这不可能用 实现.它将一个没有名称的命名空间节点添加到当前元素,但文字结果元素被 1:1 复制并保留在它们的(无)命名空间中.

UPDATE: I have just confirmed in a dialog with specialists in another forum that this is not possible to do with <xsl:namespace>. It adds a namespace node with no name to the current element, but literal result elements are copied 1:1 and remain in their (no) namespace.

W3C WG 关于 XSLT 的编辑 Michael Kay 博士是这样解释的:

Here is how Dr. Michael Kay, the Editor of the W3C WG on XSLT explains this:

"您需要在以下位置创建具有正确扩展名称的元素和属性创建它们的时间.如果这意味着使用 xsl:element,那就这样吧.xsl:namespace 只能用于创建额外的命名空间节点为元素中使用的前缀/uris 自动创建和属性名称;它不能用于修改元素的名称或属性节点.与往常一样,要理解这一点,您需要了解数据模型命名空间.元素/属性名称是一个三元组,包含 (prefix, uri,本地名称).命名空间节点是一对 (prefix, uri).有一致性如果存在包含 prefix=P uri=U 的元素或属性名称的规则那么必须有一个命名空间节点(P, U).命名空间修复过程确保在您创建一个命名空间节点时自动创建此命名空间节点元素或属性.xsl:namespace 允许您创建额外的命名空间节点,通常用于 QName-valued 中使用的命名空间内容".

"You need to create elements and attributes with the correct expanded name at the time you create them. If that means using xsl:element, so be it. xsl:namespace can only be used to create additional namespace nodes to those that are created automatically for the prefixes/uris used in element and attribute names; it can't be used to modify the name of an element or attribute node. As always, to understand this you need to understand the data model for namespaces. An element/attribute name is a triple, containing (prefix, uri, localname). A namespace node is a pair (prefix, uri). There is a consistency rule that if an element or attribute name exists containing prefix=P uri=U then there must be a namespace node (P, U). The namespace fixup process ensures that this namespace node is created automatically when you create an element or attribute. xsl:namespace is there to allow you to create additional namespace nodes, typically for namespaces used in QName-valued content".

如果需要这样的结果,解决方案是使用第二遍并将属于无命名空间"的任何元素转换为所需的新命名空间.

If such result is needed, the solution is to use a second pass and to convert any element belonging to "no namespace" to the desired new namespace.

这是在第二次传递中使用的转换(两个传递可以合并为一个样式表/转换):

This is the transformation to use in the second pass (the two passes can be combined into a single stylesheet/transformation):

<xsl:stylesheet  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:variable name="vUrl" select="'my:Url'"/>

 <xsl:template match="*[namespace-uri()='']">
   <xsl:element name="{name()}" namespace="{$vUrl}">
     <xsl:copy-of select="@*"/>
     <xsl:apply-templates/>
   </xsl:element>

 </xsl:template>
</xsl:stylesheet>

当对以下示例(pass-1-result)xml 文档应用上述转换时:

<a>
  <b>
    <c/>
  </b>
</a>

产生了想要的结果:

<a xmlns="my:Url">
    <b>
        <c/>
    </b>
</a>

这篇关于如何动态设置 XSLT 转换输出 XML 的默认命名空间声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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