当前位置 : 主页 > 网页制作 > xml >

如何动态设置XSLT转换输出XML的默认命名空间声明?

来源:互联网 收集:自由互联 发布时间:2021-06-13
我可以使用 xsl:namespace来执行此操作,但不能使用默认命名空间.如果我尝试为默认命名空间执行此操作: xsl:namespace name="" select"myUri"/ 它永远不会奏效.它要求我明确定义元素的名称空间
我可以使用< xsl:namespace>来执行此操作,但不能使用默认命名空间.如果我尝试为默认命名空间执行此操作:

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

它永远不会奏效.它要求我明确定义元素的名称空间,以便能够使用上面的空前缀声明.
我想要这个的原因是因为我有一个任务是将输入XML文件转换为另一个输出xml.输出XML有很多元素,我不想为每个元素显式设置名称空间.这就是为什么我想设置默认值而不再打扰.但必须根据源XML中的某些数据计算默认值.它在整个转换期间不会改变,但它依赖于输入XML数据.
有解决方案吗

编辑1:
支持:

>我想动态创建命名空间并将其设置为输出xml文档的默认命名空间.命名空间的uri是从输入XML中的某些数据派生的.
>如果我使用< xsl:namespace>在我的根输出元素中,我无法为它创建一个默认命名空间,只有一个前缀.即使使用前缀,它也不会传播给孩子.

编辑2:
 dkackman建议:

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

它几乎解决了这个问题.不幸的是,孩子们被变压器注入“”(空白)命名空间.如果我放一个子元素,这就是我得到的:

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

为什么变压器会将这个xmlns =“”放在孩子身上?如果我可以阻止这个,那么我找到了我的解决方案.

除了提供准确答案的@Tomalak之外,请注意< xsl:namespace>并不打算创建一个名称空间声明,供XSLT处理器使用,通常包含所有元素或属性.

< xsl:namespace>的目的是创建一个特定的命名空间节点.此节点仅具有有限的范围:当前元素或属性以及当前节点的所有子节点(如果它们未将前缀重新分配给另一个名称空间-ur).

使用< xsl:namespace>只有当我们想要为必须动态生成的namespace-uri动态创建命名空间时才是必需的(在转换开始时不是静态知道的).这种情况非常罕见.

在所有情况下,当静态地知道所需的namspace-uri时,只需将该命名空间声明为适当的可见性级别(通常在< xsl:stylesheet>指令处),然后在必须使用此命名空间的任何地方使用关联的前缀.

更新:
我刚刚在另一个论坛的专家对话中证实,这与< xsl:namespace>无法做到.它为当前元素添加了一个没有名称的命名空间节点,但是文字结果元素以1:1的形式复制并保留在它们的(无)命名空间中.

以下是XSLT W3C WG编辑Michael Kay博士如何解释:

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

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

这是在第二遍中使用的转换(两个通道可以组合成一个样式表/转换):

<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>
网友评论