【问题标题】:xpath or xslt (1.0) to find max number of rows in a grid with blocks of arbitrary lengthxpath 或 xslt (1.0) 查找网格中任意长度块的最大行数
【发布时间】:2021-12-14 16:22:00
【问题描述】:

背景和最终目标

考虑下面的 XML,它应该在图像中创建网格。每个 col 元素代表一个具有宽度和长度的单元格(无论是空的还是包含区域)。对于给定的块,起始行(纬度)是已知的,而结束行是未知的。 请注意,没有 <row latitude="6"/>,因为该行已作为 Desert StatesDeep 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>

【问题讨论】:

    标签: xslt xslt-1.0 xpath-1.0


    【解决方案1】:

    如果(正如我认为)您想知道任何时区的 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 变量应用的实际逻辑。

    【讨论】:

    • 谢谢!这完美无缺。我不会想到这个解决方案。 Apropos,使用count(。| x)= 1,我假设它执行分组,因为如果当前节点存在于键中,则count = 1。这是使用 generate-id() 替代通常的 Muenchian 模式还是不适合这里?
    • 这两种方法均在原文中提供:jenitennison.com/xslt/grouping/muenchian.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-31
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    相关资源
    最近更新 更多