Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 使用XSLT进行多级条件打印_Xml_Xslt_Formatting_Grouping - Fatal编程技术网

Xml 使用XSLT进行多级条件打印

Xml 使用XSLT进行多级条件打印,xml,xslt,formatting,grouping,Xml,Xslt,Formatting,Grouping,本周早些时候,我问了一个关于使用XSLT进行条件打印的问题,并从helderdarocha那里得到了一个非常有用的答案。不幸的是,事实证明我需要的答案比我最初想象的要复杂一些。按照他的指示,并使用Muenchian方法进行控制中断,我总结了一个我需要做的新示例 以下是我的XML: <?xml version="1.0" encoding="UTF-8"?> <group> <person> <

本周早些时候,我问了一个关于使用XSLT进行条件打印的问题,并从helderdarocha那里得到了一个非常有用的答案。不幸的是,事实证明我需要的答案比我最初想象的要复杂一些。按照他的指示,并使用Muenchian方法进行控制中断,我总结了一个我需要做的新示例

以下是我的XML:

<?xml version="1.0" encoding="UTF-8"?>
<group>
    <person>
        <datum type='medium'>Cartoon</datum>
        <datum type='firstname'>Fred</datum>
        <datum type='lastname'>Flintstone</datum>
    </person>
    <person>
        <datum type='medium'>Cartoon</datum>
        <datum type='firstname'>Wilma</datum>
        <datum type='lastname'>Flintstone</datum>
    </person>
    <person>
        <datum type='medium'>TV</datum>
        <datum type='firstname'>Luke</datum>
        <datum type='lastname'>Duke</datum>
    </person>
    <person>
        <datum type='medium'>TV</datum>
        <datum type='firstname'>Daisy</datum>
        <datum type='lastname'>Duke</datum>
    </person>
    <person>
        <datum type='medium'>Reality</datum>
        <datum type='firstname'>George</datum>
        <datum type='lastname'>Bush</datum>
    </person>
    <person>
        <datum type='medium'>Reality</datum>
        <datum type='firstname'>Barbara</datum>
        <datum type='lastname'>Bush</datum>
    </person>
</group>

卡通
弗莱德
燧石
卡通
威尔玛
燧石
电视
卢克
公爵
电视
雏菊
公爵
现实
乔治
灌木丛
现实
芭芭拉
灌木丛
这是我的XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
    <xsl:key name="medium" match="person" use="datum[@type='medium']"/>
    <xsl:key name="lastname" match="person" use="//person/datum[@type='lastname']"/>
    
    <xsl:template match="person">
        <tr>
            <td><xsl:value-of select="datum[@type='firstname']"/></td>
        </tr>
    </xsl:template>
    
    <xsl:template match="group">
        <table border="1">
            <xsl:for-each select="person[count(. | key('medium', datum[@type='medium'])[1]) = 1]/datum[@type='medium']">
                <xsl:sort/>
                <tr bgcolor="#cccccc">
                    <td><xsl:value-of select="."/></td>
                </tr>
                <xsl:for-each select="//person[count(. | key('lastname', //person/datum[@type='lastname'])[1]) = 1]/datum[@type='lastname']">
                    <xsl:sort/>
                    <tr bgcolor="#ccffcc">
                        <td><xsl:value-of select="."/></td>
                    </tr>
                    <xsl:apply-templates select="//person[datum[@type='lastname'] = current()]">
                        <xsl:sort select="datum[@type='firstname']"/>
                    </xsl:apply-templates>
                </xsl:for-each>
            </xsl:for-each>
        </table>
    </xsl:template>
</xsl:stylesheet>

这是我的输出:

但这就是我正在尝试的:

我假设我的问题是这一行:

我相信我没有正确格式化xpath,但不幸的是,我对xpath的理解仍然相对薄弱。。。我的假设是,我需要将“=1”检查移动到其他地方,但不确定如何执行此操作


一如既往,任何和所有线索都会受到赞赏。

您已经正确地开始定义“媒介”的键

我在这里使用的是generate id方法,但是您可以像以前一样使用count方法。注意这里“mode”的用法。因为我使用的是xsl:apply-templates,所以最终会有多个模板匹配person元素,因此模式会区分它们

使用此“medium”模板,您将获得不同的“lastname”条目,但使用类似的连接键(应用于当前组中由“medium”键访问的所有元素):


最后,在“lastname”模板中,您将再次使用连接键获取组中的所有person元素:

<xsl:apply-templates 
     select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />

试试这个XSLT

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

    <xsl:key name="medium" match="person" use="datum[@type='medium']" />
    <xsl:key name="medium-lastname" match="person" use="concat(datum[@type='medium'], '|', datum[@type='lastname'])" />

    <xsl:template match="group">
        <table>
            <xsl:apply-templates select="person[generate-id() = generate-id(key('medium', datum[@type='medium'])[1])]" mode="medium" />
        </table>
    </xsl:template>

    <xsl:template match="person" mode="medium">
        <tr class="medium">
            <td><xsl:value-of select="datum[@type='medium']" /></td>
        </tr>
        <xsl:apply-templates select="key('medium', datum[@type='medium'])[generate-id() = generate-id(key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))[1])]" mode="lastname" />
    </xsl:template>

    <xsl:template match="person" mode="lastname">
        <tr class="lastname">
            <td><xsl:value-of select="datum[@type='lastname']" /></td>
        </tr>
        <xsl:apply-templates select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />
    </xsl:template>

    <xsl:template match="person">
        <tr>
            <td><xsl:value-of select="datum[@type='firstname']" /></td>
        </tr> 
    </xsl:template>
</xsl:stylesheet>

当应用于此XML时

<group>
    <person>
        <datum type="medium">Cartoon</datum>
        <datum type="firstname">Fred</datum>
        <datum type="lastname">Flintstone</datum>
    </person>
    <person>
        <datum type="medium">Cartoon</datum>
        <datum type="firstname">Wilma</datum>
        <datum type="lastname">Flintstone</datum>
    </person>
    <person>
        <datum type="medium">Cartoon</datum>
        <datum type="firstname">Barney</datum>
        <datum type="lastname">Rubble</datum>
    </person>
    <person>
        <datum type="medium">TV</datum>
        <datum type="firstname">Daisy</datum>
        <datum type="lastname">Duke</datum>
    </person>
    <person>
        <datum type="medium">TV</datum>
        <datum type="firstname">George</datum>
        <datum type="lastname">Bush</datum>
    </person>
</group>

卡通
弗莱德
燧石
卡通
威尔玛
燧石
卡通
巴尼
瓦砾
电视
雏菊
公爵
电视
乔治
灌木丛
然后输出以下内容

<table>
   <tr class="medium">
      <td>Cartoon</td>
   </tr>
   <tr class="lastname">
      <td>Flintstone</td>
   </tr>
   <tr>
      <td>Fred</td>
   </tr>
   <tr>
      <td>Wilma</td>
   </tr>
   <tr class="lastname">
      <td>Rubble</td>
   </tr>
   <tr>
      <td>Barney</td>
   </tr>
   <tr class="medium">
      <td>TV</td>
   </tr>
   <tr class="lastname">
      <td>Duke</td>
   </tr>
   <tr>
      <td>Daisy</td>
   </tr>
   <tr class="lastname">
      <td>Bush</td>
   </tr>
   <tr>
      <td>George</td>
   </tr>
</table>

卡通
燧石
弗莱德
威尔玛
瓦砾
巴尼
电视
公爵
雏菊
灌木丛
乔治

通过为“介质”定义一个键,您已经正确地开始了

我在这里使用的是generate id方法,但是您可以像以前一样使用count方法。注意这里“mode”的用法。因为我使用的是xsl:apply-templates,所以最终会有多个模板匹配person元素,因此模式会区分它们

使用此“medium”模板,您将获得不同的“lastname”条目,但使用类似的连接键(应用于当前组中由“medium”键访问的所有元素):


最后,在“lastname”模板中,您将再次使用连接键获取组中的所有person元素:

<xsl:apply-templates 
     select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />

试试这个XSLT

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

    <xsl:key name="medium" match="person" use="datum[@type='medium']" />
    <xsl:key name="medium-lastname" match="person" use="concat(datum[@type='medium'], '|', datum[@type='lastname'])" />

    <xsl:template match="group">
        <table>
            <xsl:apply-templates select="person[generate-id() = generate-id(key('medium', datum[@type='medium'])[1])]" mode="medium" />
        </table>
    </xsl:template>

    <xsl:template match="person" mode="medium">
        <tr class="medium">
            <td><xsl:value-of select="datum[@type='medium']" /></td>
        </tr>
        <xsl:apply-templates select="key('medium', datum[@type='medium'])[generate-id() = generate-id(key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))[1])]" mode="lastname" />
    </xsl:template>

    <xsl:template match="person" mode="lastname">
        <tr class="lastname">
            <td><xsl:value-of select="datum[@type='lastname']" /></td>
        </tr>
        <xsl:apply-templates select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />
    </xsl:template>

    <xsl:template match="person">
        <tr>
            <td><xsl:value-of select="datum[@type='firstname']" /></td>
        </tr> 
    </xsl:template>
</xsl:stylesheet>

当应用于此XML时

<group>
    <person>
        <datum type="medium">Cartoon</datum>
        <datum type="firstname">Fred</datum>
        <datum type="lastname">Flintstone</datum>
    </person>
    <person>
        <datum type="medium">Cartoon</datum>
        <datum type="firstname">Wilma</datum>
        <datum type="lastname">Flintstone</datum>
    </person>
    <person>
        <datum type="medium">Cartoon</datum>
        <datum type="firstname">Barney</datum>
        <datum type="lastname">Rubble</datum>
    </person>
    <person>
        <datum type="medium">TV</datum>
        <datum type="firstname">Daisy</datum>
        <datum type="lastname">Duke</datum>
    </person>
    <person>
        <datum type="medium">TV</datum>
        <datum type="firstname">George</datum>
        <datum type="lastname">Bush</datum>
    </person>
</group>

卡通
弗莱德
燧石
卡通
威尔玛
燧石
卡通
巴尼
瓦砾
电视
雏菊
公爵
电视
乔治
灌木丛
然后输出以下内容

<table>
   <tr class="medium">
      <td>Cartoon</td>
   </tr>
   <tr class="lastname">
      <td>Flintstone</td>
   </tr>
   <tr>
      <td>Fred</td>
   </tr>
   <tr>
      <td>Wilma</td>
   </tr>
   <tr class="lastname">
      <td>Rubble</td>
   </tr>
   <tr>
      <td>Barney</td>
   </tr>
   <tr class="medium">
      <td>TV</td>
   </tr>
   <tr class="lastname">
      <td>Duke</td>
   </tr>
   <tr>
      <td>Daisy</td>
   </tr>
   <tr class="lastname">
      <td>Bush</td>
   </tr>
   <tr>
      <td>George</td>
   </tr>
</table>

卡通
燧石
弗莱德
威尔玛
瓦砾
巴尼
电视
公爵
雏菊
灌木丛
乔治

这里的关键是使用
按介质分组,然后按姓氏分组。以下这些应该是有效的。您可以看到它在这里工作:


这里的关键是使用
按介质分组,然后按姓氏分组。以下这些应该是有效的。您可以看到它在这里工作:



请不要发布代码和数据的截图。把实际的代码和数据放在你的文章中,格式化为代码。当我这样做时,它会告诉我代码格式不正确,然后不让我发布。相信我,我更愿意这样做。将代码粘贴到文本编辑器中,将所有制表符转换为4个空格,将所有内容缩进4个空格,然后粘贴到SO编辑窗口中,在代码上下各有一个空行。如果你真的,真的无法用代码编辑文章,请转到,
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <table border="1">
            <xsl:for-each-group select="/group/person" group-by="datum[@type='medium']">
                <tr bgcolor="#cccccc"><td><xsl:value-of select="current-grouping-key()"/></td></tr>

                <xsl:for-each-group select="current-group()" group-by="datum[@type='lastname']">
                    <tr bgcolor="#ccffcc"><td><xsl:value-of select="current-grouping-key()"/></td></tr>

                <xsl:for-each select="current-group()">
                    <tr><td><xsl:value-of select="./datum[@type='firstname']"/></td></tr>
                </xsl:for-each>

            </xsl:for-each-group>
          </xsl:for-each-group>
        </table>
    </xsl:template>

</xsl:transform>