知道谁是具有更多Child节点的元素

时间:2013-10-30 23:58:52

标签: xml xslt xsd

我是XML文档,有投票。我必须知道更多选票的建议是什么,我该怎么做? 我正在使用XSLT进行转换,但我无法找到方法。

XML:

<tns:vote>
  <tns:alternative>
    <tns:description>50% do valor recebido das propinas será aplicado em investigação</tns:description>
      <tns:votes>
        <tns:member_vote member_id="i2"/>
        <tns:member_vote member_id="i6"/>
        <tns:member_vote member_id="i7"/>
      </tns:votes>
    <tns:description>20% do valor recebido das propinas será aplicado em investigação</tns:description>
      <tns:votes>
        <tns:member_vote member_id="i4"/>
        <tns:member_vote member_id="i5"/>
      </tns:votes>
  </tns:alternative>        
</tns:vote>

在这个例子中,第一个描述应该是赢家提议。

3 个答案:

答案 0 :(得分:2)

在xslt 1.0中,您可以使用xsl:sort指令,如:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tns="tns">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <result>
            <xsl:apply-templates select="tns:vote/tns:alternative" />
        </result>
    </xsl:template>

    <xsl:template match="tns:alternative">
        <!-- Process all description -->
        <xsl:for-each select="tns:description">
            <!-- Sort them descending by count votes in the first following sibling tns:votes -->
            <xsl:sort select="count(following-sibling::tns:votes[1]/tns:member_vote)" order="descending" />
            <!-- Do anything with that, e.g. make a deep copy -->
            <xsl:copy-of select="." />
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

生成xml,其描述按投票顺序排序。

如果您只需要一个值(“获胜者”),您可以使用例如每个人都在<xsl:if test="position() = 1">...</xsl:if>内。

答案 1 :(得分:1)

此解决方案结合了@Jirka的XSLT 1.0方法和我对多个最佳投票的评论,并简单地输出所有最佳投票的列表。它使用准备步骤来确定最佳投票数,然后在第二步中选择具有最佳计数的所有投票。请注意,在第二步中,我们不再需要排序。如果有必要,我们仍然可以进行排序,如果有另一个合理的标准打破最佳选票的对称性。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="1.0"
    xmlns:tns="mynamespace"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
  <xsl:strip-space elements="*"/>

  <xsl:template match="/tns:vote/tns:alternative">

    <!-- compute the best vote count; just the number not the elements -->
    <xsl:variable name="best_vote">
      <xsl:for-each select="tns:description">
        <xsl:sort select="count(following-sibling::tns:votes[1]/tns:member_vote)" order="descending"/>
        <xsl:if test="position() = 1">
          <xsl:value-of select="count(following-sibling::tns:votes[1]/tns:member_vote)"/>
        </xsl:if>
      </xsl:for-each>
    </xsl:variable>

    <tns:result>
      <xsl:for-each select="tns:description"> <!-- we need not sort here anymore! -->

        <!-- only dump those entries which match the best vote count -->
        <xsl:if test="count(following-sibling::tns:votes[1]/tns:member_vote) = number($best_vote)">

          <tns:winning_vote vote_count="{count(following-sibling::tns:votes[1]/tns:member_vote)}">
            <xsl:copy-of select="."/>
            <xsl:copy-of select="following-sibling::tns:votes[1]/tns:member_vote"/>
          </tns:winning_vote>

        </xsl:if>

      </xsl:for-each>
    </tns:result>
  </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

在XSLT 2.0中,您可以将for-each-group标记与sort一起使用。以下XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="2.0"
    xmlns:tns="mynamespace"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

  <xsl:template match="/tns:vote/tns:alternative">

    <xsl:for-each-group select="*" group-starting-with="tns:description">
      <xsl:sort select="count(current-group()[2]/tns:member_vote)" order="descending"/>

      <xsl:if test="position() = 1">

        <tns:winning_alternative vote_count="{count(current-group()[2]/tns:member_vote)}>
          <xsl:copy-of select="current-group()"/>
        </tns:winning_alternative>

      </xsl:if>

    </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>

产生此结果

<?xml version="1.0" encoding="UTF-8"?>
  <tns:winning_alternative xmlns:tns="mynamespace" vote_count="3">
   <tns:description>50% do valor recebido das propinas será aplicado em investigação</tns:description>
   <tns:votes>
      <tns:member_vote member_id="i2"/>
      <tns:member_vote member_id="i6"/>
      <tns:member_vote member_id="i7"/>
    </tns:votes>
</tns:winning_alternative>      

请注意,如果多个替代方案具有相同的最佳投票,XSLT将只选择其中一个。