新手问题。我必须创建一个这样的交叉表报告:
SC TIN Total 3 2 South East 2 0 Gold Coast 2 0 North 1 2 Cairns 0 1 Townsville 1 1
使用下面的(简化)XML:
<DATASETLIST>
<DATASET entity="SC">
<ROW>
<District>GOLD COAST</District>
<Region>SOUTH EAST</Region>
</ROW>
<ROW>
<District>GOLD COAST</District>
<Region>SOUTH EASTERN</Region>
</ROW>
<ROW>
<District>TOWNSVILLE</District>
<Region>NORTH</Region>
</ROW>
</DATASET>
<DATASET entity="TIN">
<ROW>
<District>TOWNSVILLE</District>
<Region>NORTH</Region>
</ROW>
<ROW>
<District>CAIRNS</District>
<Region>NORTH</Region>
</ROW>
</DATASET>
</DATASETLIST>
我实际上已经得到了主要报告,但层次结构是硬编码的(例如,计数SC与“黄金海岸”相关联)但由于可能数据不佳,我可能会遗漏一些节点,所以我想建立一个基于的独特层次结构数据,然后我可以为每个节点调用我的“计数”模板。
我已经得到了一个观点(见下文),我可以在其中生成一个区域排序列表,但它不是唯一的,并且区域不在每个区域内排序。我以为我可以以某种方式创建一个独特的层次结构变量,然后用xsl:for-each逻辑处理它。
但我不知道这是可行的还是推荐的方法。这可能是一个非常简单的解决方案,但我不知道如何去做。请用简单(并且清楚解释)的术语表达任何答案。
<xsl:for-each select="//Region[not(Region=preceding-sibling::Region)]">
<xsl:sort select="."/>
<xsl:for-each select=".">
<xsl:value-of select="."/> -
<xsl:for-each select="../District">
<xsl:value-of select="."/><br/>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
答案 0 :(得分:1)
这就是你如何做到的。不过,我担心这并不容易和直截了当。输入XMl的结构方式使得访问相关节点变得更加困难。
例如,在某些地方,您需要访问自然不在上下文中的节点。为了解决这个问题,我使用变量和参数。
但它非常通用,即您可以处理任意数量的DATASETS
,Regions
或Districts
。它创建一个HTML表来显示计数。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="html">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="DATASETLIST">
<xsl:element name="head">
<xsl:element name="title">
<xsl:text>DATASET counts</xsl:text>
</xsl:element>
</xsl:element>
<xsl:element name="body">
<xsl:element name="table">
<xsl:attribute name="border">1</xsl:attribute>
<xsl:call-template name="tbl"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="tbl">
<xsl:param name="regions" select="distinct-values(DATASET/ROW/Region)"/>
<xsl:param name="rows" select="DATASET/ROW"/>
<xsl:param name="datasets" select="DATASET"/>
<!--header row-->
<xsl:element name="tr">
<xsl:element name="th"/>
<xsl:for-each select="$datasets">
<xsl:element name="th">
<xsl:value-of select="@entity"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
<!--Totals row-->
<xsl:element name="tr">
<xsl:element name="td">
<xsl:element name="b">
<xsl:text>Total</xsl:text>
</xsl:element>
</xsl:element>
<xsl:for-each select="$datasets">
<xsl:element name="td">
<xsl:value-of select="count(ROW)"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
<xsl:element name="tr"/>
<!--region rows-->
<xsl:for-each select="$regions">
<xsl:variable name="region" select="."/>
<xsl:element name="tr">
<xsl:element name="td">
<xsl:element name="b">
<xsl:value-of select="."/>
</xsl:element>
</xsl:element>
<xsl:for-each select="$datasets">
<xsl:element name="td">
<xsl:value-of select="count(ROW/Region[.=$region])"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
<!--district rows-->
<xsl:for-each select="distinct-values($rows[Region=$region]/District)">
<xsl:variable name="district" select="."/>
<xsl:element name="tr">
<xsl:element name="td">
<xsl:value-of select="."/>
</xsl:element>
<xsl:for-each select="$datasets">
<xsl:element name="td">
<xsl:value-of select="count(ROW/District[.=$district])"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
<xsl:element name="tr"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>