XML 元素名称中包含的 XSLT 命名空间 URI

Posted

技术标签:

【中文标题】XML 元素名称中包含的 XSLT 命名空间 URI【英文标题】:XLST Namespace URI included in XML element name 【发布时间】:2020-05-06 06:00:06 【问题描述】:

所以我在样式表中声明了我的命名空间,像这样

<xmlns:address="http://base.google.com/ns/1.0"

下面是我的整个 XSLT 转换模板

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:address="http://base.google.com/ns/1.0" exclude-result-prefixes="address">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="success"/>
<xsl:template match="paging"/>
<xsl:template match="orders">
    <xsl:element name="Items" >
        <xsl:for-each select="order">
            <xsl:element name="item">
                <xsl:element name="entity_id">
                    <xsl:value-of select="order_no"/>
                </xsl:element>
                <xsl:element name="grand_total">
                    <xsl:value-of select="total"/>
                </xsl:element>
                <xsl:element name="shipping_amount">
                    <xsl:value-of select="shipping"/>
                </xsl:element>
                <xsl:element name="state">
                    <xsl:value-of select="status"/>
                </xsl:element>
                <xsl:element name="created_at">
                    <xsl:value-of select="created"/>
                </xsl:element>
                <xsl:for-each select="client">
                    <address:customer_id>
                        <xsl:value-of select="client_id"/>
                    </address:customer_id>
                    <xsl:element name="address:firstname">
                        <xsl:value-of select="first_name"/>
                    </xsl:element>
                    <xsl:element name="address:lastname">
                        <xsl:value-of select="last_name"/>
                    </xsl:element>  
                    <xsl:element name="address:company">
                        <xsl:value-of select="company"/>
                    </xsl:element>  
                    <xsl:element name="address:street">
                        <xsl:value-of select="street"/>
                    </xsl:element> 
                    <xsl:element name="address:city">
                        <xsl:value-of select="city"/>
                    </xsl:element>  
                    <xsl:element name="address:telephone">
                        <xsl:value-of select="phone"/>
                    </xsl:element>  
                    <xsl:element name="address:email">
                        <xsl:value-of select="email"/>
                    </xsl:element>  
                    <xsl:element name="address:region">
                        <xsl:value-of select="country"/>
                    </xsl:element>
                </xsl:for-each>
                <xsl:for-each select="items">
                    <xsl:for-each select="item">
                        <xsl:element name="product_name">
                            <xsl:value-of select="name"/>
                        </xsl:element>
                        <xsl:element name="product_id">
                            <xsl:value-of select="product_id"/>
                        </xsl:element>
                        <xsl:element name="price">
                            <xsl:value-of select="price"/>
                        </xsl:element>
                        <xsl:element name="item_id">
                            <xsl:value-of select="item_id"/>
                        </xsl:element>
                        <xsl:element name="tax">
                            <xsl:value-of select="tax"/>
                        </xsl:element>
                        <xsl:element name="qty">
                            <xsl:value-of select="qty"/>
                        </xsl:element>                            
                    </xsl:for-each>                        
                </xsl:for-each>
            </xsl:element>
        </xsl:for-each>
    </xsl:element>
</xsl:template>

我的意图是创建像 &lt;address:lastname&gt; 这样的命名空间节点,但我得到的结果是 &lt;address:firstname xmlns:address="http://base.google.com/ns/1.0"&gt; 我对 XSLT 还很陌生,所以不太确定问题是什么,看到一些帖子提到不包括命名空间前缀选项也不起作用

【问题讨论】:

不确定您的期望。如果不将前缀绑定到 nemespace,则无法使用前缀,因此您报告的结果是正确的。 有什么办法可以做到吗? 首先,考虑使用文字结果元素(例如&lt;address:firstname&gt;...&lt;/address:firstname&gt;)而不是xsl:element,这仅在您想要计算元素名称时才需要。当然,如果您希望根元素声明并具有前缀,那么您需要确保不使用exclude-result-prefixes="address" 是的,我也尝试了所有这些组合,xmlns:address="http://base.google.com/ns/1.0" 仍然跟随,只是如果我不删除它,那么需要它为 &lt;address:firstname&gt; 格式的 php 代码将无法识别它完全是一列 【参考方案1】:

首先,您报告的结果是正确的:格式良好的 XML 文档如果不将前缀绑定到命名空间,就无法使用前缀。如果您的目标应用程序无法处理此问题,则说明它不符合 XML 规范。

但是,您可以尝试将命名空间声明移至根元素,而不是在每个 address::* 元素上重复。而不是:

<xsl:element name="Items" >

使用:

<Items xmlns:address="http://base.google.com/ns/1.0">

并从您的 xsl:stylesheet 开始标记中删除相同的命名空间声明。这应该会产生一个结构如下的文档:

<Items xmlns:address="http://base.google.com/ns/1.0">
  <item>
    <entity_id/>
    <grand_total/>
    <shipping_amount/>
    <state/>
    <created_at/>
    <address:customer_id/>
    <address:firstname/>
    <address:lastname/>
    <address:company/>
    <address:street/>
    <address:city/>
    <address:telephone/>
    <address:email/>
    <address:region/>
  </item>
</Items>

希望您的目标应用程序可以比您的(语义相同的)当前结果处理得更好。


如 cmets 中所述,您也可以通过将所有其他 xsl:element 指令替换为文字结果元素来简化样式表。

【讨论】:

我不确定这是否能解决问题&lt;xsl:element name="Items" xmlns:address="http://base.google.com/ns/1.0"&gt; 我也尝试过这个解决方案,并且还用文字元素进行了替换 哦,抱歉,现在我改成这个&lt;Items xmlns:address="http://base.google.com/ns/1.0"后它工作了,谢谢你的帮助

以上是关于XML 元素名称中包含的 XSLT 命名空间 URI的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 XSLT 从 XML 中删除名称空间

重命名元素的 XSLT 问题——更改命名空间

名称空间作为使用 XSLT 处理的文档的变量

如何使用 xslt 将父节点命名空间复制到子元素?

xslt copy-of到结果文档中的不同命名空间

如何使用 XSLT 将名称空间添加到我的 XML 的根元素?