2016-12-15 122 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