xpath 或 xslt (1.0) 在具有任意长度块的网格中查找最大行数
xpath or xslt (1.0) to find max number of rows in a grid with blocks of arbitrary length
上下文和终极objective
考虑下面的 XML 应该在图像中创建网格。每个 col 元素代表一个具有宽度和长度的单元格(无论是空单元格还是包含区域)。对于给定的块,起始行(纬度)是已知的,结束行不是。
请注意,没有 <row latitude="6"/>
,因为该行已经作为 Desert States 和 Deep South 块的一部分用完了。同样,第 3 行缺少 <col timezone="PDT"/>
,因为该单元格已被 North West.
占用
我需要知道制作最终网格需要多少行。在这个例子中,我需要 10 行。
问题
我目前的方法是计算出长度总和最大的时区。
sum(//col[@timezone='EDT']/@length)
上面的 xpath 的问题是时区在这里是硬编码的(在实际应用程序中实际上是一个具有大量可能值的轴)。
我试过键和 muenchian 分组但无济于事。
我可以使用什么 xpath 1.0 或 xslt 1.0?
XML
<rows>
<row latitude="1">
<cols>
<col timezone="PDT" width="1" length="1">Canada</col>
<col timezone="CDT" width="1" length="1">Canada</col>
<col timezone="EDT" width="1" length="1">Canada</col>
</cols>
</row>
<row latitude="2">
<cols>
<col timezone="PDT" width="1" length="2">North West</col>
<col timezone="CDT" width="1" length="1"></col>
<col timezone="EDT" width="1" length="1"></col>
</cols>
</row>
<row latitude="3">
<cols>
<col timezone="CDT" width="1" length="1"></col>
<col timezone="EDT" width="1" length="2">NY/NJ</col>
</cols>
</row>
<row latitude="4">
<cols>
<col timezone="PDT" width="1" length="3">Desert States</col>
<col timezone="CDT" width="1" length="1"></col>
</cols>
</row>
<row latitude="5">
<cols>
<col timezone="CDT" width="2" length="6">Deep South / Bahamas</col>
<col timezone="EDT" width="2" length="6">Deep South / Bahamas</col>
</cols>
</row>
<row latitude="7">
<cols>
<col timezone="PDT" width="1" length="2">California</col>
</cols>
</row>
</rows>
如果(正如我认为)您想知道任何时区的length
的最大总和,您需要将col
元素分组他们的时区,按总和对组进行排序,并获得第一个(或最后一个,取决于排序顺序)组的总和值。
这是一个例子:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="col-by-TZ" match="col" use="@timezone" />
<xsl:template match="/rows">
<xsl:variable name="n">
<xsl:for-each select="row/cols/col[count(. | key('col-by-TZ', @timezone)[1]) = 1]">
<xsl:sort select="sum(key('col-by-TZ', @timezone)/@length)" data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="sum(key('col-by-TZ', @timezone)/@length)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<output>
<test>
<xsl:value-of select="$n"/>
</test>
</output>
</xsl:template>
</xsl:stylesheet>
将 test
部分替换为您要使用 $n
变量应用的实际逻辑。
上下文和终极objective
考虑下面的 XML 应该在图像中创建网格。每个 col 元素代表一个具有宽度和长度的单元格(无论是空单元格还是包含区域)。对于给定的块,起始行(纬度)是已知的,结束行不是。
请注意,没有 <row latitude="6"/>
,因为该行已经作为 Desert States 和 Deep South 块的一部分用完了。同样,第 3 行缺少 <col timezone="PDT"/>
,因为该单元格已被 North West.
我需要知道制作最终网格需要多少行。在这个例子中,我需要 10 行。
问题
我目前的方法是计算出长度总和最大的时区。
sum(//col[@timezone='EDT']/@length)
上面的 xpath 的问题是时区在这里是硬编码的(在实际应用程序中实际上是一个具有大量可能值的轴)。 我试过键和 muenchian 分组但无济于事。
我可以使用什么 xpath 1.0 或 xslt 1.0?
XML
<rows>
<row latitude="1">
<cols>
<col timezone="PDT" width="1" length="1">Canada</col>
<col timezone="CDT" width="1" length="1">Canada</col>
<col timezone="EDT" width="1" length="1">Canada</col>
</cols>
</row>
<row latitude="2">
<cols>
<col timezone="PDT" width="1" length="2">North West</col>
<col timezone="CDT" width="1" length="1"></col>
<col timezone="EDT" width="1" length="1"></col>
</cols>
</row>
<row latitude="3">
<cols>
<col timezone="CDT" width="1" length="1"></col>
<col timezone="EDT" width="1" length="2">NY/NJ</col>
</cols>
</row>
<row latitude="4">
<cols>
<col timezone="PDT" width="1" length="3">Desert States</col>
<col timezone="CDT" width="1" length="1"></col>
</cols>
</row>
<row latitude="5">
<cols>
<col timezone="CDT" width="2" length="6">Deep South / Bahamas</col>
<col timezone="EDT" width="2" length="6">Deep South / Bahamas</col>
</cols>
</row>
<row latitude="7">
<cols>
<col timezone="PDT" width="1" length="2">California</col>
</cols>
</row>
</rows>
如果(正如我认为)您想知道任何时区的length
的最大总和,您需要将col
元素分组他们的时区,按总和对组进行排序,并获得第一个(或最后一个,取决于排序顺序)组的总和值。
这是一个例子:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="col-by-TZ" match="col" use="@timezone" />
<xsl:template match="/rows">
<xsl:variable name="n">
<xsl:for-each select="row/cols/col[count(. | key('col-by-TZ', @timezone)[1]) = 1]">
<xsl:sort select="sum(key('col-by-TZ', @timezone)/@length)" data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="sum(key('col-by-TZ', @timezone)/@length)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<output>
<test>
<xsl:value-of select="$n"/>
</test>
</output>
</xsl:template>
</xsl:stylesheet>
将 test
部分替换为您要使用 $n
变量应用的实际逻辑。