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