Найти максимальное значение всех дочерних элементов и получить его родительский элемент в XSLT - PullRequest
4 голосов
/ 11 августа 2010

Используя приведенный ниже XML, мне нужно выяснить, какой человек работал больше часов на каждом сайте. Например, в приведенном ниже XML человек 1 работал 8 часов на сайте 1, а человек 2 работал только 6 часов. Таким образом, результат должен содержать лицо 1 и сайт 1 в преобразованном XML. Если часы равны, выберите первого человека.

РЕДАКТИРОВАТЬ: я хочу, чтобы это было реализовано с использованием XSLT 1.0.

<root>
    <WorkSite Person="P1" Site="S1">
        <Hours>8</Hours>
    </WorkSite>
    <WorkSite Person="P1" Site="S2">
        <Hours>2</Hours>
    </WorkSite>
    <WorkSite Person="P1" Site="S3">
        <Hours>9</Hours>
    </WorkSite>
    <WorkSite Person="P2" Site="S1">
        <Hours>6</Hours>
    </WorkSite>
    <WorkSite Person="P2" Site="S2">
        <Hours>10</Hours>
    </WorkSite>
    <WorkSite Person="P2" Site="S3">
        <Hours>2</Hours>
    </WorkSite>
</root>

Результат XSLT-преобразования должен быть таким:

<root> 
    <WorkSite Person="P1" Site="S1"/>  
    <WorkSite Person="P2" Site="S2"/> 
    <WorkSite Person="P1" Site="S3"/> 
</root>

Ответы [ 3 ]

7 голосов
/ 11 августа 2010

Это преобразование XSLT 1.0 :

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

 <xsl:key name="kSiteByName" match="@Site" use="."/>

 <xsl:key name="kWorksiteBySite"
   match="WorkSite" use="@Site"/>

 <xsl:variable name="vSites" select=
  "/*/*/@Site[generate-id()
             =
              generate-id(key('kSiteByName',.)[1])
              ]"
  />

 <xsl:template match="/">
  <root>
    <xsl:for-each select="$vSites">
      <xsl:for-each select="key('kWorksiteBySite', .)">
        <xsl:sort select="Hours" data-type="number"
         order="descending"/>
        <xsl:if test="position()=1">
         <xsl:copy>
           <xsl:copy-of select="@*"/>
         </xsl:copy>
        </xsl:if>
      </xsl:for-each>
    </xsl:for-each>
  </root>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<root>
    <WorkSite Person="P1" Site="S1">
        <Hours>8</Hours>
    </WorkSite>
    <WorkSite Person="P1" Site="S2">
        <Hours>2</Hours>
    </WorkSite>
    <WorkSite Person="P1" Site="S3">
        <Hours>9</Hours>
    </WorkSite>
    <WorkSite Person="P2" Site="S1">
        <Hours>6</Hours>
    </WorkSite>
    <WorkSite Person="P2" Site="S2">
        <Hours>10</Hours>
    </WorkSite>
    <WorkSite Person="P2" Site="S3">
        <Hours>2</Hours>
    </WorkSite>
</root>

дает желаемый, правильный результат :

<root>
    <WorkSite Person="P1" Site="S1"/>
    <WorkSite Person="P2" Site="S2"/>
    <WorkSite Person="P1" Site="S3"/>
</root>

Примечание :

  1. Использование метода Мюнхена для группировки для нахождения всех различных значений Site.

  2. Максимум пути определяется путем сортировки по убыванию и получения первого результата из отсортированного списка узлов.

2 голосов
/ 11 августа 2010
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:template match="/">
      <root>
         <xsl:for-each-group select="*/WorkSite" group-by="@Site">
            <WorkSite Person="{(current-group()[Hours = max(current-group()/Hours)])[1]/@Person}" Site="{current-grouping-key()}" />
         </xsl:for-each-group>
      </root>
   </xsl:template>

</xsl:stylesheet>
0 голосов
/ 12 августа 2010

Решение XSLT 1.0.Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:key name="BySite" match="WorkSite" use="@Site"/>
 <xsl:template match="root">
  <root>
   <xsl:for-each select="/*/WorkSite[count(.|key('BySite',@Site)[1])=1]">
    <WorkSite Person="{key('BySite',@Site)
                       [not(key('BySite',@Site)/Hours 
                            > Hours)]/@Person}"
              Site="{@Site}" />
   </xsl:for-each>
  </root>
 </xsl:template>
</xsl:stylesheet>

Вывод:

<root>
 <WorkSite Person="P1" Site="S1" />
 <WorkSite Person="P2" Site="S2" />
 <WorkSite Person="P1" Site="S3" />
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...