2016-12-15 171 views
0

給出像下面XSL節點集值

<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
<root> 
<config> 
<kids block="A"> 
<owner name="bob"/> 
<owner name="alice"/> 
</kids> 
<kids block="B"> 
<owner name="Jimmy"/> 
<owner name="Bimmy"/> 
</kids> 
<kids block="C"> 
<owner name="Johnny"/> 
</kids> 
</config> 
<objects> 
    <object owner="bob"> 
    <name>fish</name> 
    <value>200</value> 
    <part>head</part> 
    <part>tail</part> 
    </object> 
    <object owner="alice"> 
    <name>cat</name> 
    <value>100</value> 
    <part>claws</part> 
    <part>head</part> 
    <part>tail</part> 
    </object> 
    <object owner="Jimmy"> 
    <name>DoubleDragon</name> 
    <value>0</value> 
    <part>dragon</part> 
    </object> 
</objects> 
</root> 

我希望得到以下

Output: 
A - bob - fish 
    alice - cat 
B - Jimmy - DoubleDragon 

上市在每塊的所有對象名稱,然後每一個XML所有者基礎。每個所有者只有一個對象,所以這不成問題。

是否可以在XSL 1.0中生成這樣的輸出?

我通過無效for-each取得的成績是遍歷每個區塊,然後通過其所有者,並搜索<objects>部分中的每個所有者。但是,這不允許看中,分層輸出,而不是我得到

A - bob - fish 
A - alice - cat // note the duplicate A block name 
B - Jimmy - DoubleDragon 

我用

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:template match="/"> 
<xsl:for-each select="/root/config/kids/owner"> 
<xsl:variable name="ownername" select="./@name"/> 
<xsl:text>  
</xsl:text> 
<xsl:variable name="ownedObject" select="/root/objects/object[@owner=$ownername]"/> 
<xsl:if test="$ownedObject"> 
<xsl:value-of select="../@block"/> <xsl:text>-</xsl:text> 
<xsl:value-of select="./@name"/> <xsl:text>-</xsl:text> 
<xsl:value-of select="$ownedObject/name/text()"/> 
</xsl:if> 
</xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 
+0

你可以顯示你目前試過的XSLT嗎?謝謝! –

+0

@TimC我添加了有效的輸入和當前的XSL(用於測試目的)。 – teodron

回答

1

首先,我建議您使用key將對象鏈接到它們的所有者。現在

,以達到想要的結果,你可以這樣做:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" encoding="UTF-8" /> 

<xsl:key name="obj" match="object" use="@owner" /> 

<xsl:template match="/root"> 
    <!-- for each block that has actual owners --> 
    <xsl:for-each select="config/kids[key('obj', owner/@name)]"> 
     <!-- for each actual owner in this block --> 
     <xsl:for-each select="owner[key('obj', @name)]"> 
      <xsl:choose> 
       <!-- for the first owner in this block --> 
       <xsl:when test="position()=1"> 
        <xsl:value-of select="../@block"/> 
        <xsl:text> - </xsl:text> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:text> - </xsl:text> 
       </xsl:otherwise> 
      </xsl:choose>  
      <xsl:value-of select="@name"/> 
      <xsl:text> - </xsl:text> 
      <xsl:value-of select="key('obj', @name)/name"/> 
      <xsl:text>&#10;</xsl:text> 
     </xsl:for-each> 
    </xsl:for-each>  
</xsl:template> 

</xsl:stylesheet> 

注意嵌套xsl:for-each指令確保位置()函數在當前的環境中運行塊。


另一種方法將通過其所有者的塊來處理它們的對象和group

1

我通過實現什麼當前XSL無效的for-each是遍歷每個區塊,然後通過其所有者並搜索該區域中的每個所有者。但是,這不允許一個花哨的,分層輸出,而不是我得到...

這樣做是相反的。遍歷kids元素,併爲每個元素迭代匹配的objects/object元素。

+0

我添加了一個XSL片段。但是,我不確定這是否足夠。我無法弄清擺脫冗餘的邏輯 - 我怎樣才能避免多次輸出塊的名稱?我如何確保輸出塊的名稱當且僅當該塊兒童至少有一個對應的對象? – teodron