Xml XSLT;查找文档中最频繁的元素值

Xml XSLT;查找文档中最频繁的元素值,xml,xslt,Xml,Xslt,道歉,如果这是一个非常简单的问题;我不太使用XSLT,在网上也找不到很多建议,因为搜索结果中有很多污染 我有一个如下形式的XML文档。它的主要目的是通过XSLT以几种方式重新格式化,以便以两种不同的格式显示 <desk> <drawer> <contents>pencils</contents> <quantity>2</quantity> </drawer> <drawer>

道歉,如果这是一个非常简单的问题;我不太使用XSLT,在网上也找不到很多建议,因为搜索结果中有很多污染

我有一个如下形式的XML文档。它的主要目的是通过XSLT以几种方式重新格式化,以便以两种不同的格式显示

<desk>
<drawer>
    <contents>pencils</contents>
    <quantity>2</quantity>
</drawer>
<drawer>
    <contents>pens</contents>
    <quantity>15</quantity>
</drawer>
<drawer>
    <contents>pencils</contents>
    <quantity>3</quantity>
</drawer>
<drawer>
    <contents>rulers</contents>
    <quantity>2</quantity>
</drawer>
</desk>

铅笔
2.
钢笔
15
铅笔
3.
统治者
2.
我想从xml中提取两条信息:I)平均数量;ii)xml中出现次数最多的内容(即“pencils”,因为它出现两次,而不是数量最多的“pens”)。其思想是,可以通过管道将其传输到一个非常简单的shell脚本中。因此,我认为获取此信息的最简单方法是编写两个简短的xsl样式表,然后使用xsltproc获取数据

第一条信息似乎是直截了当的。样式表的核心是这一行:

<xsl:value-of select="(sum(drawer/quantity)) div (count(drawer))" />

但是我有点被第二个卡住了

我想我可以使用类似这样的方法来循环每个内容的列表:

<xsl:for-each select="drawer[not(contents = preceding-sibling::drawer/contents)]" />

但我不太确定如何计算包含$current_内容的元素数量及其内容元素的值。我也看不到一种按结果排序的简单方法,这样我就可以得到内容中最常遇到的值的名称

我觉得在XSLT2.0中使用各种group by选项更容易做到这一点,但不幸的是,xsltproc似乎不支持这一点。任何帮助都将受到感激

非常感谢,


Jacob

通过
排序
元素对每个进行排序。只需按数量排序,然后(如果您只需要最频繁的)添加一个
标记,以仅获取循环中的第一个

<xsl:for-each select="drawer">
   <xsl:sort select="quantity" data-type="number" order="descending"/>
   <xsl:if test="position()=1">
      Most frequent: <xsl:value-of select="contents"> with <xsl:value-of select="quantity"> items
   </xsl:if>
</xsl:for-each>

最常见的:与项目

正如XSLT解决了许多问题一样,我认为您的答案是。根据您感兴趣的任何数据进行分组,一个for-each对照将允许您使用xsl:sort,然后对第一个结果执行您需要的任何操作

未经测试,顶部,可能是一个清洁方式代码:

<xsl:key name="average" match="desk/drawer/contents" use="text()"/>

<xsl:template match="/">
    <xsl:for-each select="desk/drawer/contents[generate-id() = generate-id(key('average',text())[1])]">     
        <xsl:sort select="count(//desk/drawer/contents[text()=current()])"  order="descending"/>
        <xsl:if test="position()=1">
            Most common value: "<xsl:value-of select="current()"/>" (<xsl:value-of select="count(//desk/drawer/contents[text()=current()])"/>)
        </xsl:if>       
    </xsl:for-each>
</xsl:template>

最常见的值:“”()

已经有一段时间了,但我认为这样做可能会奏效

首先清点所有内容

<xsl:variable name="tally">
  <xsl:for-each select="drawer">
     <contents count="{count(drawer[contents = current()/contents])}"><xsl:value-of select="contents"/></contents>
  </xsl:for-each>
</xsl:variable>

请注意,$tally每次都会对重复条目进行计数,其中包含:

<contents count="2">pencils</contents>
<contents count="1">pens</contents>
<contents count="2">pencils</contents>
<contents count="1">rulers</contents>
铅笔
钢笔
铅笔
统治者
然后使用此项查找没有其他计数更高的项目:

<xsl:variable name="mostfrequentcontents" select="$tally/contents[not($tally/contents/@count > @count)]" />


根据xslt处理器的不同,您可能需要使用节点集函数将$tally转换为节点集。

啊,对不起,我应该解释得更清楚些。这将产生结果“pencil”,因为有17支铅笔。我想让它生产“铅笔”,因为“铅笔”出现两次,“钢笔”和“尺子”出现一次;那很有帮助。但我不知道该怎么做,只是“你需要什么”这一点。通过“内容”对xml进行分组,是否有一种简单的方法可以计算特定“内容”值在xml中出现的次数?非常感谢;这真的很有帮助而且很有效!现在我只需要弄清楚它是如何工作的!:)Muenchian技术将所有可能的类型分组,因此您将循环限制在可能的候选数量上(如果您预期重复次数少或候选数量少,则可能适得其反)。for each仅允许您使用基于每个不同值的计数的排序。if只是裁剪输出,遗憾的是没有与XSLT等价的中断:)谢谢;我永远也无法用xslt来思考这些方法!使用xsltproc,我得到了以下信息,因此我认为我需要使用节点集。我正在查阅手册。。。XPath错误:无效类型运行时错误:file port.xsl第11行元素变量无法计算变量“mostfrequentcontents”的表达式。