简体   繁体   English

在 XSL 转换中附加命名空间

[英]Append namespace in XSL transformation

I have following XML input:我有以下 XML 输入:

<my_value>test123</my_value>

Here is XSL这是 XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" exclude-result-prefixes="array fn map math xhtml xs err" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
    
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="*">
        <xsl:element name="my_node">
            <xsl:namespace name="tns" select="'http://www.example.com'"/>
            <xsl:element name="my_child">
                <xsl:value-of select="my_value"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>
  
</xsl:stylesheet>

As an output I want to have:作为我想要的输出:

<tns:my_node xmlns:tns="http://www.example.com">
    <tns:my_child>test123</tns:my_child>
</tns:my_node>

How to modify XSL to achieve my goal?如何修改 XSL 以实现我的目标?

You're making life much too complicated here and you're getting some things wrong.你让这里的生活变得太复杂了,而且你做错了一些事情。

<xsl:template match="my_value">
    <xsl:element name="my_node">
        <xsl:namespace name="tns" select="'http://www.example.com'"/>
        <xsl:element name="my_child">
            <xsl:value-of select="my_value"/>
        </xsl:element>
    </xsl:element>
</xsl:template>

Firstly, xsl:namespace is only needed if you want to inject a namespace that isn't used in any element or attribute names.首先,只有当您想注入一个未在任何元素或属性名称中使用的命名空间时,才需要xsl:namespace When you're creating elements and attributes you need to say what namespace they're in, and the namespace nodes/declarations will then be created automatically.当您创建元素和属性时,您需要说明它们所在的命名空间,然后将自动创建命名空间节点/声明。

Secondly, the context node for the template is the my_value element so you get its value using .其次,模板的上下文节点是 my_value 元素,因此您可以使用. , not using my_value . ,不使用my_value Context is everything.语境就是一切。

So you could write:所以你可以写:

<xsl:template match="*">
    <xsl:element name="tns:my_node" namespace="http://www.example.com"/>
        <xsl:element name="my_child" namespace="http://www.example.com">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:element>
</xsl:template>

But xsl:element is needed only when the name of the element you're constructing isn't known statically.但是xsl:element仅当您正在构造的元素的名称不是静态已知时才需要。 When the name is fixed, it's much better to use a literal result element:名称固定后,最好使用文字结果元素:

<xsl:template match="*">
    <tns:my_node xmlns:tns="http://www.example.com"/>
        <tns:my_child>
            <xsl:value-of select="."/>
        </tns:my_child>
    </tns:my_node>
</xsl:template>

Finally with XSLT 3.0 if you set the expand-text="yes" option you can simplify this further to:最后使用 XSLT 3.0,如果您设置 expand-text="yes" 选项,您可以进一步将其简化为:

<xsl:template match="*">
    <tns:my_node xmlns:tns="http://www.example.com"/>
        <tns:my_child>{.}</tns:my_child>
    </tns:my_node>
</xsl:template>

A simple use of literal result elements should suffice:简单地使用文字结果元素就足够了:

<xsl:template match="my_value">
  <tns:my_node xmlns:tns="http://www.example.com">
    <tns:my_child>
      <xsl:value-of select="."/>
    </tns:my_child>
  </tns:my_node>
</xsl:template>

As you seem to be using XSLT 3 you could also use a text value template instead of xsl:value-of :由于您似乎在使用 XSLT 3,您还可以使用文本值模板而不是xsl:value-of

<xsl:template match="my_value" expand-text="yes">
  <tns:my_node xmlns:tns="http://www.example.com">
    <tns:my_child>{.}</tns:my_child>
  </tns:my_node>
</xsl:template>

Not sure I got the whole intent, but could you try this:不确定我是否理解了整个意图,但你能试试这个吗:

<xsl:stylesheet xmlns:tns="http://www.example.com" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" exclude-result-prefixes="array fn map math xhtml xs err" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
    
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="*">
        <xsl:element name="tns:my_node">
            <xsl:element name="tns:my_child">
                <xsl:value-of select="."/>
            </xsl:element>
        </xsl:element>
    </xsl:template>
  
</xsl:stylesheet>

So, we did the following amends:所以,我们做了以下修改:

  1. Introduced xmlns:tns="http://www.example.com" attribute to the xsl:stylesheet root element instead of dedicated xsl:namespace tagxmlns:tns="http://www.example.com"属性引入xsl:stylesheet根元素,而不是专用的xsl:namespace标记
  2. Applied the namespace prefix to my_node and my_child right in place (now it's legit because we introduced the prefix)将命名空间前缀应用到my_nodemy_child就地(现在它是合法的,因为我们引入了前缀)
  3. Did a selection of "."做了一个选择"." instead of my_value而不是my_value

As a result, we have:结果,我们有:

<tns:my_node xmlns:tns="http://www.example.com">
   <tns:my_child>test123</tns:my_child>
</tns:my_node>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM