簡體   English   中英

無法為使用XSL的子項添加名稱空間前綴

[英]Cannot add namespace prefix to children using 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:前綴不存在。 Order標頭中還有其他xmlns =“”(由於某種原因)。 我無法弄清楚為其余元素添加ns:前綴(如錯誤和列表)。

首先,如果父母已經擁有它,為什么我需要為孩子們​​添加前綴。 父命名空間是否指示子節點/屬性命名空間?

其次,我想按預期在上面的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: namespace中。

  3. 如何為Order元素或其任何后代元素指定N2:名稱空間。

如果您真的關心輸出中的命名空間前綴是什么,那么您將需要在模板中使用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>

您應該知道名稱空間很重要 ,而名稱空間前綴不是 它是語法糖。 您可以將多個名稱空間前綴綁定到同一名稱空間-ur,或者不具有名稱空間前綴,並且仍然生成相同類型的元素(綁定到特定名稱空間-uri)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM