2013-03-13 140 views
1

我正在編寫一個轉換,我想將xmlns屬性(xmlns="myNS")添加到根節點。XSLT:意外的繼承null xmlns屬性

應用轉換時,xmlns屬性包含在某些子元素中。

我無法弄清楚如何改變我的轉換,只將它應用到根元素。

XML

<db:result xmlns:db="http://www.sonicsw.com/esb/service/dbservice"> 
    <db:resultSet version="1.1"> 
     <db:row> 
      <id>a</id> 
      <value1>b</value1> 
      <value2>c</value2> 
     </db:row> 
     <db:row> 
      <id>a</id> 
      <value1>d</value1> 
      <value2>e</value2> 
     </db:row> 
     <db:row> 
      <id>a</id> 
      <value1>f</value1> 
      <value2>g</value2> 
     </db:row> 
     <db:row> 
      <id>a</id> 
      <value1>h</value1> 
      <value2>i</value2> 
     </db:row> 
    </db:resultSet> 
</db:result> 

XSLT

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:db="http://www.sonicsw.com/esb/service/dbservice" 
    exclude-result-prefixes="db"> 
    <xsl:template match="/"> 
      <xsl:for-each-group select="//db:row" group-by="id"> 
       <xsl:sort select="id"/> 
        <xsl:apply-templates select="." mode="document"/> 
      </xsl:for-each-group> 
    </xsl:template> 

    <xsl:template match="db:row" mode="document"> 
     <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNS"> 
      <id><xsl:value-of select="id"/></id> 
      <lines> 
       <xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/> 
      </lines> 
     </root>   
    </xsl:template> 

    <xsl:template match="db:row" mode="line"> 
     <line> 
      <valueof1><xsl:value-of select="value1"/></valueof1> 
      <valueof2><xsl:value-of select="value2"/></valueof2> 
     </line> 
    </xsl:template> 
</xsl:stylesheet> 

XML輸出

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="myNS"> 
    <id>a</id> 
    <lines> 
     <line xmlns=""> 
      <valueof1>b</valueof1> 
      <valueof2>c</valueof2> 
     </line> 
     <line xmlns=""> 
      <valueof1>d</valueof1> 
      <valueof2>e</valueof2> 
     </line> 
     <line xmlns=""> 
      <valueof1>f</valueof1> 
      <valueof2>g</valueof2> 
     </line> 
     <line xmlns=""> 
      <valueof1>h</valueof1> 
      <valueof2>i</valueof2> 
     </line> 
    </lines> 
</root> 

XML期望輸出

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="myNS"> 
    <id>a</id> 
    <lines> 
     <line> 
      <valueof1>b</valueof1> 
      <valueof2>c</valueof2> 
     </line> 
     <line> 
      <valueof1>d</valueof1> 
      <valueof2>e</valueof2> 
     </line> 
     <line> 
      <valueof1>f</valueof1> 
      <valueof2>g</valueof2> 
     </line> 
     <line> 
      <valueof1>h</valueof1> 
      <valueof2>i</valueof2> 
     </line> 
    </lines> 
</root> 

注:我發現這個職位存在,但不能鍛鍊如何應用建議的解決方案:

回答

2

在文字結果元素一個樣式表從xmlns聲明中取得他們的名稱空間中的樣式表,即內

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="myNS"> 
     <id><xsl:value-of select="id"/></id> 
     <lines> 
      <xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/> 
     </lines> 
    </root> 

root元素及其所有前綴的子女都在myNS命名空間。然而,在

<xsl:template match="db:row" mode="line"> 
    <line> 
     <valueof1><xsl:value-of select="value1"/></valueof1> 
     <valueof2><xsl:value-of select="value2"/></valueof2> 
    </line> 
</xsl:template> 

linevalueofN元素沒有命名空間,因爲有在範圍上沒有默認xmlns在樣式表這一點。

所以,簡單的答案是將xmlns="myNS"root元素移動在db:row模板成頂級xsl:stylesheet代替:

<xsl:stylesheet version="2.0" 
    xmlns="myNS" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:db="http://www.sonicsw.com/esb/service/dbservice" 
    exclude-result-prefixes="db"> 
    <xsl:template match="/"> 
      <xsl:for-each-group select="//db:row" group-by="id"> 
       <xsl:sort select="id"/> 
        <xsl:apply-templates select="." mode="document"/> 
      </xsl:for-each-group> 
    </xsl:template> 

    <xsl:template match="db:row" mode="document"> 
     <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
      <id><xsl:value-of select="id"/></id> 
      <lines> 
       <xsl:apply-templates select="//db:row[id=current()/id]" mode="line"/> 
      </lines> 
     </root>   
    </xsl:template> 

    <xsl:template match="db:row" mode="line"> 
     <line> 
      <valueof1><xsl:value-of select="value1"/></valueof1> 
      <valueof2><xsl:value-of select="value2"/></valueof2> 
     </line> 
    </xsl:template> 
</xsl:stylesheet> 

但要注意的是這個樣式表不會產生結構良好的輸出,如果原始XML中的row元素並不全都具有相同的ID,因爲您將獲得多個沒有單個父元素的root元素。您可能希望在match="/"模板中添加包裝元素以確保輸出格式正確。

P.S.因爲你在for-each-group很可能是更有效地失去了mode="document"模板,並直接將其內容的F-E-G裏面,然後用current-group而不必爲[id=current()/id]過濾的:

<xsl:template match="/"> 
     <xsl:for-each-group select="//db:row" group-by="id"> 
      <xsl:sort select="current-grouping-key()"/> 
      <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
       <id><xsl:value-of select="current-grouping-key()"/></id> 
       <lines> 
        <xsl:apply-templates select="current-group()" mode="line"/> 
       </lines> 
      </root>   
     </xsl:for-each-group> 
    </xsl:template>