我在这里查了很多答案,我想我差不多了。有一件事是困扰我(并且由于某些原因,我的同伴需要它)如下:
<?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: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:前缀不存在。 Order标头中还有其他xmlns =“”(由于某种原因)。我无法弄清楚为其余元素添加ns:前缀(如错误和列表)。
首先,如果父母已经拥有它,为什么我需要为孩子们添加前缀。父命名空间是否指示子节点/属性命名空间?
答案 0 :(得分:7)
此转换(仅限42行):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*">
<xsl:element name="ns:{name()}"
namespace="http://schemas.foo.com/response">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="/MyRoot">
<xsl:element name="ns:{name()}"
namespace="http://schemas.foo.com/response">
<xsl:copy-of select=
"document('')/*/namespace::*[name()='N1' or name()='N2']"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="MyRequest">
<xsl:element name="N1:{name()}"
namespace="http://schemas.foo.com/request">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="*[ancestor-or-self::Order]">
<xsl:element name="N2:{name()}"
namespace="http://schemas.foo.com/details">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<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:MyRoot xmlns:N1="http://schemas.foo.com/request" xmlns:N2="http://schemas.foo.com/details" xmlns:ns="http://schemas.foo.com/response">
<N1:MyRequest CompletionCode="0" CustomerID="9999999999"/>
<ns:List TotalList="1">
<N2:Order CustomerID="999999999" OrderNo="0000000001" 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:MyRoot>
请注意:
使用<xsl:element>
及其name
和namespace
属性。
identity template
如何演变为变换的前两个模板 - 这个决定是基于这样一个事实:只有在特殊情况下,元素才不能出现在ns:
中命名空间。
如何为N2:
元素或其任何后代元素指定Order
命名空间。
答案 1 :(得分:4)
如果您真的关心输出中的命名空间前缀是什么,那么您将需要在模板中使用literal-result元素,而不是xsl:element
构造函数:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.foo.com/response"
xmlns:N1="http://schemas.foo.com/request"
xmlns:N2="http://schemas.foo.com/details">
<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">
<ns:MyNewRoot>
<xsl:apply-templates/>
</ns:MyNewRoot>
</xsl:template>
<xsl:template match="MyRequest">
<N1:MyRequest>
<xsl:apply-templates select="@* | node()"/>
</N1:MyRequest>
</xsl:template>
<xsl:template match="List">
<ns:List>
<xsl:apply-templates select="@* | node()"/>
</ns:List>
</xsl:template>
<xsl:template match="Order">
<N2:Order>
<xsl:apply-templates select="@* | node()"/>
</N2:Order>
</xsl:template>
<xsl:template match="BillToAddress">
<N2:BillToAddress>
<xsl:apply-templates select="@* | node()"/>
</N2:BillToAddress>
</xsl:template>
<xsl:template match="ShipToAddress">
<N2:ShipToAddress>
<xsl:apply-templates select="@* | node()"/>
</N2:ShipToAddress>
</xsl:template>
<xsl:template match="Totals">
<N2:Totals>
<xsl:apply-templates select="@* | node()"/>
</N2:Totals>
</xsl:template>
<xsl:template match="Errors" />
</xsl:stylesheet>
您应该知道名称空间是重要的,名称空间前缀不是。它是语法糖。您可以将多个名称空间前缀绑定到同一名称空间-uri,或者不具有名称空间前缀,并且仍然生成相同类型的元素(绑定到特定名称空间-uri)。