gpt4 book ai didi

xml - 无法使用 XSL 向子项添加命名空间前缀

转载 作者:数据小太阳 更新时间:2023-10-29 01:47:08 24 4
gpt4 key购买 nike

我在这里检查了很多答案,我想我快到了。困扰我的一件事(出于某种原因,我的同伴需要它)如下:

我有以下输入 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: 前缀不存在。订单 header 中还有附加的 xmlns=""(出于某种原因)。我无法弄清楚为其余元素(如错误和列表)添加 ns: 前缀。

首先,如果父项已经有了前缀,为什么我还需要为子项添加前缀。父 namespace 不决定子节点/属性 namespace 吗?

其次,我想按预期在上面的 XML 中添加前缀,我该如何使用 XSL 做到这一点?

最佳答案

这个转换(只有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>

请注意:

  1. 使用<xsl:element>及其 namenamespace属性。

  2. 如何identity template已经演变为转换的前两个模板——这个决定是基于这样一个事实,即只有在特殊情况下,元素才不能在 ns: 中。命名空间。

  3. 如何N2:Order 指定命名空间元素或其任何后代元素。

关于xml - 无法使用 XSL 向子项添加命名空间前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2976626/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com