2014-07-21 117 views
0

我得到這個XML(「其他」元素有不同的名稱,只是跳過他們爲清楚起見):如何根據不同元素的值過濾xml元素?

<root> 
<elements1> 
<element> 
<id>1</id> 
<other>a</other> 
<other>b</other> 
<other>c</other> 
</element> 
<element><id>2</id> 
<other>a</other> 
<other>b</other> 
<other>c</other> 
</element> 
<element><id>3</id> 
<other>a</other> 
<other>b</other> 
<other>c</other> 
</element> 
</elements1> 

<elements2> 
<element> 
<id2>1</id2> 
<other2>a</other2> 
<other2>b</other2> 
<other2>c</other2> 
</element> 
<element> 
<id2>2</id2> 
<other2>a</other2> 
<other2>b</other2> 
<other2>c</other2> 
</element> 
<elements2> 
</root> 

我需要那麼就說明這樣的事情對其進行過濾:

<root> 
<elements> 
    <element> 
    <id>1</id> 
    <id2>1</id2> 
    <other>a</other> 
    <other>b</other> 
    <other>c</other> 
    <other2>a</other2> 
    <other2>b</other2> 
    <other2>c</other2> 
    </element> 
    <element> 
    <id>2</id> 
    <id2>2</id2> 
    <other>a</other> 
    <other>b</other> 
    <other>c</other> 
    <other2>a</other2> 
    <other2>b</other2> 
    <other2>c</other2> 
    </element> 
</elements> 
</root> 

所以它應該將兩個不同元素的子元素放在一起,並將它們作爲一個由id和id2過濾的元素。

不知道該怎麼做。我試過兩個for-each元素來過濾xml,但它不起作用。

+2

它是一個分組的問題。您可以使用XSLT 2.0和XSLT 2.0處理器(如Saxon 9或AltovaXML)嗎?然後使用for-each-group select =「// element」group-by =「id,id2」'。使用XSLT 1.0閱讀Muenchian分組http://www.jenitennison.com/xslt/grouping/muenchian.xml。 –

回答

1

下面是一個使用密鑰的XSLT樣式表2.0:

<xsl:stylesheet 
    version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output indent="yes"/> 

<xsl:key name="id2" match="elements2/element" use="id2"/> 

<xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* , node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="root"> 
    <xsl:copy> 
    <elements> 
     <xsl:apply-templates select="elements1/element[key('id2', id)]"/> 
    </elements> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="elements1/element"> 
    <xsl:variable name="el2" select="key('id2', id)"/> 
    <xsl:copy> 
    <xsl:copy-of select="id, $el2/id2, (., $el2)/(* except (id, id2))"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

類似的方法用XSLT 1.0是

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output indent="yes"/> 

<xsl:key name="id2" match="elements2/element" use="id2"/> 

<xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="root"> 
    <xsl:copy> 
    <elements> 
     <xsl:apply-templates select="elements1/element[key('id2', id)]"/> 
    </elements> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="elements1/element"> 
    <xsl:variable name="el2" select="key('id2', id)"/> 
    <xsl:copy> 
    <xsl:copy-of select="id | $el2/id2 | *[not(self::id)] | $el2/*[not(self::id2)]"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

這工作正常,但我不太明白如何?你能解釋一下你做了些什麼嗎? –

+0

首先,我定義一個鍵'',讓我可以通過他們的ID有效地訪問'elements2/element'。然後在'root'的模板中,我只處理那些具有相應的'elements2/element'的'elements1/element',使用key函數來建立它。然後'elements1/element'的模板再次使用key函數來選擇交叉引用的'elements2/element',以便能夠輸出它的子元素,如'id2'和其他元素。 –

+0

謝謝你完美地解釋了這個例子!偉大的工作:) –