2016-11-23 54 views
0

源XML文檔的多個元素:刷新位置使用XSLT爲具有相同名稱的

<item> 
<p languageCode="en">en</p> 
<p languageCode="fr">fr</p> 
<c languageCode="de">de</c> 
<c languageCode="nl">nl</c> 
</item> 

轉換的需要的結果必須是這個XML文檔:

<item> 
<p pos="1">en</p> 
<p pos="2">fr</p> 
<c pos="1">de</c> 
<c pos="2">nl</c> 
</item> 

使用XSLT是有可能實現它?

+0

請解釋** **邏輯通過'pos'值被確定。 –

+0

一旦元素名稱更改,pos值再次被重置爲1。 @ michael.hor257k – divya

+0

我已經把你的問題回覆到我回答時的情況。我建議你發表一個與你的顯着不同的情況下的新問題(並確保解釋規則,而不是期待我們從這個例子中推導出它們。 –

回答

2

在XSLT 2.0,你可以這樣做:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> 

<xsl:template match="/item"> 
    <xsl:copy> 
     <xsl:for-each-group select="*" group-adjacent="name()"> 
      <xsl:apply-templates select="current-group()"/> 
     </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="p | c"> 
    <xsl:copy> 
     <xsl:attribute name="pos" select="position()"/> 
     <xsl:value-of select="."/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

哇,太棒了 – divya

+0

我已經編輯了這個問題,現在它的更復雜的結構我無法破解 – divya

+0

@divya對不起,我們沒有這樣做 –

1

XSLT 1.0:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/*"> 
    <item><xsl:apply-templates/></item> 
</xsl:template> 


    <xsl:template match="/*/*"> 
     <xsl:copy> 
     <xsl:attribute name="pos"> 
      <xsl:value-of select="count(preceding-sibling::*[name()=name(current())])+1"/> 
     </xsl:attribute> 
     <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 
    </xsl:stylesheet> 

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/*"> 
    <item><xsl:apply-templates/></item> 
</xsl:template> 

<xsl:template match="/*/*"> 
    <xsl:copy> 
    <xsl:attribute name="pos" 
        select="count(preceding-sibling::*[name()=name(current())])+1"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

另一個XSLT 2.0解決方案

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:key name="kByName" match="/*/*" use="name()"/> 

<xsl:template match="/*"> 
    <item><xsl:apply-templates/></item> 
</xsl:template> 

<xsl:template match="/*/*"> 
    <xsl:copy> 
    <xsl:attribute name="pos" 
        select="index-of(key('kByName', name())/generate-id(), generate-id())"/> 
    <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

<item> 
    <p languageCode="en">en</p> 
    <p languageCode="fr">fr</p> 
    <c languageCode="de">de</c> 
    <c languageCode="nl">nl</c> 
</item> 

所有這三個解決方案產生想要的,正確的結果:

<item> 
    <p pos="1">en</p> 
    <p pos="2">fr</p> 
    <c pos="1">de</c> 
    <c pos="2">nl</c> 
</item> 

不要e

所有這些解決方案都是通用 - 它們不依賴於名稱,數量,名稱數量或元素順序。

例如,當下面的XML文檔應用:

<item> 
    <p languageCode="en">en</p> 
    <p languageCode="fr">fr</p> 
    <c languageCode="de">de</c> 
    <c languageCode="nl">nl</c> 
    <d languageCode="es">es</d> 
    <d languageCode="bg">bg</d> 
    <d languageCode="pl">pl</d> 
</item> 

所有三種解決方案產生想要的,正確的結果

<item> 
    <p pos="1">en</p> 
    <p pos="2">fr</p> 
    <c pos="1">de</c> 
    <c pos="2">nl</c> 
    <d pos="1">es</d> 
    <d pos="2">bg</d> 
    <d pos="3">pl</d> 
</item>