XSLT寻找不同的组合(XSLT finding distinct combinations)

2019-10-19 06:14发布

我是初学者XSLT。 我想找到的年,月,日和时间都是独一无二的组合。

我有下面的XML文件转换:

<Plans>
    <Plan Name="Plan_1">
        <Book Name="Book_1">
            <Time Name="AAA">
                <Property Name="Year" Value="2001"/>
                <Property Name="Month" Value="01"/>
                <Property Name="Day" Value="10"/>
                <Property Name="Hour" Value="12"/>
            </Time>
            <Time Name="BBB">
                <Property Name="Year" Value="2001"/>
                <Property Name="Month" Value="01"/>
                <Property Name="Day" Value="10"/>
                <Property Name="Hour" Value="12"/>
            </Time>
            <Time Name="CCC">
                <Property Name="Year" Value="2004"/>
                <Property Name="Month" Value="02"/>
                <Property Name="Day" Value="11"/>
                <Property Name="Hour" Value="04"/>
            </Time>
            <Time Name="DDD">
                <Property Name="Year" Value="2004"/>
                <Property Name="Month" Value="03"/>
                <Property Name="Day" Value="20"/>
                <Property Name="Hour" Value="04"/>
            </Time>
        </Book>
        <Book Name="Book_22">
            <Time Name="CCC">
                <Property Name="Year" Value="2001"/>
                <Property Name="Month" Value="01"/>
                <Property Name="Day" Value="10"/>
                <Property Name="Hour" Value="12"/>
            </Time>
            <Time Name="DDD">
                <Property Name="Year" Value="2002"/>
                <Property Name="Month" Value="03"/>
                <Property Name="Day" Value="23"/>
                <Property Name="Hour" Value="03"/>
            </Time>
            <Time Name="EEE">
                <Property Name="Year" Value="2002"/>
                <Property Name="Month" Value="03"/>
                <Property Name="Day" Value="23"/>
                <Property Name="Hour" Value="03"/>
            </Time>
            <Time Name="FFF">
                <Property Name="Year" Value="2004"/>
                <Property Name="Month" Value="02"/>
                <Property Name="Day" Value="11"/>
                <Property Name="Hour" Value="04"/>
            </Time>
        </Book>
    </Plan>
</Plans>

输入XML已累计总共八个组合(四从每本书)。

我只是想知道不同的组合。 所以输出应该有6种组合,因为有两个相同的组合。 书籍的名称并不重要。 我只是想看看有多少组合也有。 而刚刚从1标签的数量......它不一定是任何顺序,虽然它可以通过时间进行排序...如果它是太难标签号码,那么我只需要只得到不同的组合.. 。

<Times>
    <Time Value="1">
        <Property Name="Year" Value="2001"/>
        <Property Name="Month" Value="01"/>
        <Property Name="Day" Value="10"/>
        <Property Name="Hour" Value="12"/>
    </Time>
    <Time Value="2">
        <Property Name="Year" Value="2004"/>
        <Property Name="Month" Value="02"/>
        <Property Name="Day" Value="11"/>
        <Property Name="Hour" Value="04"/>
    </Time>
    <Time Value="3">
        <Property Name="Year" Value="2004"/>
        <Property Name="Month" Value="03"/>
        <Property Name="Day" Value="20"/>
        <Property Name="Hour" Value="04"/>
    </Time>
    <Time Value="4">
        <Property Name="Year" Value="2001"/>
        <Property Name="Month" Value="01"/>
        <Property Name="Day" Value="10"/>
        <Property Name="Hour" Value="12"/>
    </Time>
    <Time Value="5">
        <Property Name="Year" Value="2002"/>
        <Property Name="Month" Value="03"/>
        <Property Name="Day" Value="23"/>
        <Property Name="Hour" Value="03"/>
    </Time>
</Times>

我试图阅读,每个组。 但我不能让它工作...是否有是四个循环或东西,因为有四个调性质? 请帮我...

Answer 1:

类似于其他的答案,你也可以利用的xsl:对,每个组在这里。

<xsl:for-each-group select=".//Time" group-by="string-join(Property/@Value, '|')">

如果你的XSLT是使用身份模板,然后你可以输出这个组内的不同时间元素简单地这样做

 <Time Value="{position()}">
     <xsl:apply-templates />
 </Time>

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="/*">
    <Times>
      <xsl:for-each-group select=".//Time" group-by="string-join(Property/@Value, '|')">
          <Time Value="{position()}">
              <xsl:apply-templates />
          </Time>
      </xsl:for-each-group>
    </Times>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

现在,你提的意见(但不是在这个问题)大约有多个计划的元素,但如果你想在所有计划要素选择不同的时间元素,或者为每个单独的计划不同的元素,你都没有说。

假设你是要显示每个单独的计划不同的时间要素,然后只是一个小的调整就可以了。 你只是有效地匹配计划元件,并在该分组

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

  <xsl:template match="Plan">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select=".//Time" group-by="string-join(Property/@Value, '|')">
          <Time Value="{position()}">
              <xsl:apply-templates />
          </Time>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

请注意,这些假设你的属性元素的顺序,将始终是相同的(“年”,“月”,“日”,“小时”)。 如果没有,你可以通过执行以下操作解决这个问题

<xsl:for-each-group select=".//Time" group-by="concat(
     Property[@Name='Year']/@Value, '|', 
     Property[@Name='Month']/@Value, '|',
     Property[@Name='Day']/@Value, '|',
     Property[@Name='Hour']/@Value, '|')">


Answer 2:

采用

distinct-values(/Times/Time/string-join(Property/@Value, '|'))

以获得不同的值。 然后,在必要的时候使用令牌化()分割成其分量场。



Answer 3:

下面的样式表是建立在由@迈克尔凯给出了答案。 这只是说明了解决方案,证明它正在工作。 请接受他的答案!

编号输出元件不硬,最简单的方法是使用position()中的属性值的模板。

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/Plans">
      <Times>
         <xsl:for-each select="distinct-values(//Time/string-join(Property/@Value, '|'))">
            <xsl:variable name="tokens" select="tokenize(.,'\|')"/>
            <Time Value="{position()}">
               <Property Name="Year" Value="{$tokens[1]}"/>
               <Property Name="Month" Value="{$tokens[2]}"/>
               <Property Name="Day" Value="{$tokens[3]}"/>
               <Property Name="Hour" Value="{$tokens[4]}"/>
            </Time>
         </xsl:for-each>
      </Times>
   </xsl:template>

</xsl:stylesheet>

产量

正如@Tim c项,你可能期待4个结果元素。

<?xml version="1.0" encoding="UTF-8"?>
<Times>
   <Time Value="1">
      <Property Name="Year" Value="2001"/>
      <Property Name="Month" Value="01"/>
      <Property Name="Day" Value="10"/>
      <Property Name="Hour" Value="12"/>
   </Time>
   <Time Value="2">
      <Property Name="Year" Value="2004"/>
      <Property Name="Month" Value="02"/>
      <Property Name="Day" Value="11"/>
      <Property Name="Hour" Value="04"/>
   </Time>
   <Time Value="3">
      <Property Name="Year" Value="2004"/>
      <Property Name="Month" Value="03"/>
      <Property Name="Day" Value="20"/>
      <Property Name="Hour" Value="04"/>
   </Time>
   <Time Value="4">
      <Property Name="Year" Value="2002"/>
      <Property Name="Month" Value="03"/>
      <Property Name="Day" Value="23"/>
      <Property Name="Hour" Value="03"/>
   </Time>
</Times>


文章来源: XSLT finding distinct combinations