无法使用 XSL 向子级添加命名空间前缀
我在这里检查了很多答案,我想我已经差不多了。困扰我的一件事(并且由于某种原因我的同伴需要它)如下:
我有以下输入 XML:
<?xml version="1.0" encoding="utf-8"?>
<MyRoot>
<MyRequest CompletionCode="0" CustomerID="9999999999"/>
<List TotalList="1">
<Order CustomerID="999999999" OrderNo="0000000001" Status="Shipped">
<BillToAddress ZipCode="22221"/>
<ShipToAddress ZipCode="22222"/>
<Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</Order>
</List>
<Errors/>
</MyRoot>
我被要求生成这个:
<ns:MyNewRoot xmlns:ns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<ns:List TotalList="1">
<N2:Order CustomerID="999999999" Level="Preferred" Status="Shipped">
<N2:BillToAddress ZipCode="22221"/>
<N2:ShipToAddress ZipCode="22222"/>
<N2:Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</N2:Order>
</ns:List>
<ns:Errors/>
</ns:MyNewRoot>
注意 N2:Order 的子级也需要 N2: 前缀以及 ns : 其余元素的前缀。
我使用下面的 XSL 转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/MyRoot">
<MyNewRoot xmlns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<xsl:apply-templates/>
</MyNewRoot>
</xsl:template>
<xsl:template match="/MyRoot/MyRequest">
<xsl:element name="N1:{name()}" namespace="http://schemas.foo.com/request">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="/MyRoot/List/Order">
<xsl:element name="N2:{name()}" namespace="http://schemas.foo.com/details">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这个不处理 ns(我无法弄清楚这一点)。当我使用 AltovaXML 处理上述 XSL 转换时,我最终得到以下结果:
<MyNewRoot xmlns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<List xmlns="" TotalList="1">
<N2:Order CustomerID="999999999" Level="Preferred" Status="Shipped">
<BillToAddress ZipCode="22221"/>
<ShipToAddress ZipCode="22222"/>
<Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</N2:Order>
</List>
<Errors/>
</MyNewRoot>
请注意,在 XSL 转换之后,Order 子项的 N2: 前缀不存在。订单标头中还附加了 xmlns="" (出于某种原因)。我无法弄清楚如何为其余元素(如错误和列表)添加 ns: 前缀。
首先,如果父级已经有前缀,为什么我需要为子级添加前缀。父命名空间是否规定了子节点/属性命名空间?
其次,我想按预期在上述 XML 中添加前缀,如何使用 XSL 做到这一点?
I checked many answers here and I think I am almost there. One thing that is bugging me (and for some reason my peer needs it) follows:
I have the following input XML:
<?xml version="1.0" encoding="utf-8"?>
<MyRoot>
<MyRequest CompletionCode="0" CustomerID="9999999999"/>
<List TotalList="1">
<Order CustomerID="999999999" OrderNo="0000000001" Status="Shipped">
<BillToAddress ZipCode="22221"/>
<ShipToAddress ZipCode="22222"/>
<Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</Order>
</List>
<Errors/>
</MyRoot>
I was asked to produce this:
<ns:MyNewRoot xmlns:ns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<ns:List TotalList="1">
<N2:Order CustomerID="999999999" Level="Preferred" Status="Shipped">
<N2:BillToAddress ZipCode="22221"/>
<N2:ShipToAddress ZipCode="22222"/>
<N2:Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</N2:Order>
</ns:List>
<ns:Errors/>
</ns:MyNewRoot>
Note the children of the N2:Order also needs N2: prefix as well as the ns: prefix for the rest of the elements.
I use the XSL transformation below:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/MyRoot">
<MyNewRoot xmlns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<xsl:apply-templates/>
</MyNewRoot>
</xsl:template>
<xsl:template match="/MyRoot/MyRequest">
<xsl:element name="N1:{name()}" namespace="http://schemas.foo.com/request">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="/MyRoot/List/Order">
<xsl:element name="N2:{name()}" namespace="http://schemas.foo.com/details">
<xsl:copy-of select="namespace::*"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
This one doesn't process the ns (I couldn't figure this out). When I process thru the above the XSL transformation with AltovaXML I end up with below:
<MyNewRoot xmlns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<List xmlns="" TotalList="1">
<N2:Order CustomerID="999999999" Level="Preferred" Status="Shipped">
<BillToAddress ZipCode="22221"/>
<ShipToAddress ZipCode="22222"/>
<Totals Tax="0.50" SubTotal="10.00" Shipping="4.95"/>
</N2:Order>
</List>
<Errors/>
</MyNewRoot>
Note that N2: prefix for the children of Order is not there after the XSL transformation. Also additional xmlns="" in the Order header (for some reason). I couldn't figure out putting the ns: prefix for the rest of the elements (like Errors and List).
First of all, why would I need to put the prefix for the children if the parent already has it. Doesn't the parent namespace dictate the children nodes/attribute namespaces?
Secondly, I want to add the prefixes in the above XML as expected, how can I do that with XSL?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此转换(仅 42 行):
应用于提供的 XML 文档时:
产生所需结果:
请注意:
及其name
和namespace
属性的使用。身份模板
如何演变为转换的前两个模板 - 这一决定基于以下事实:只有在特殊情况下,元素才不能出现在ns 中:
命名空间。如何为
Order
元素或其任何后代元素指定N2:
命名空间。This transformation (only 42 lines):
when applied on the provided XML document:
produces the wanted result:
Do note:
The use of
<xsl:element>
and itsname
andnamespace
attributes.How the
identity template
has been evolved into the first two templates of the transformation -- this decision was based on the fact that only in exceptional cases an element must not be in thens:
namespace.How the
N2:
namespace is specified for theOrder
element or any of its descendent elements.如果您确实关心输出中的名称空间前缀,那么您将希望在模板中使用字面量结果元素,而不是
xsl:element
构造函数:您应该知道名称空间 很重要,命名空间前缀不。它是语法糖。您可以将多个命名空间前缀绑定到同一个命名空间 uri,或者没有命名空间前缀,但仍然生成相同类型的元素(绑定到特定的命名空间 uri)。
If you really care about what the namespace prefixes are in the output then you will want to use literal-result elements in your templates, rather than the
xsl:element
constructor:You should know that the namespace is important, the namespace-prefix is not. It is syntactic sugar. You can have multiple namespace-prefixes bound to the same namespace-uri, or not have a namespace prefix and still produce the same type of elements(bound to a particular namespace-uri).