групповой ответ по месяцам и годам - PullRequest
2 голосов
/ 09 января 2011

Я хочу написать xslt, чтобы получить ответ для входного XML.заранее спасибо.Я хочу сгруппировать выходные данные таким образом, чтобы комбинация месяц-год не повторялась для каждой детали сотрудника.

Входной XML:

<resultset>
    <row>
        <column>
            <name>Month</name>
            <value>2</value>
        </column>
        <column>
            <name>Year</name>
            <value>2010</value>
        </column>
        <column>
            <name>EmpName</name>
            <value>Anu</value>
        </column>
        <column>
            <name>Age</name>
            <value>24</value>
        </column>
    </row>
    <row>
        <column>
            <name>Month</name>
            <value>2</value>
        </column>
        <column>
            <name>Year</name>
            <value>2010</value>
        </column>
        <column>
            <name>EmpName</name>
            <value>Nancy</value>
        </column>
        <column>
            <name>Age</name>
            <value>26</value>
        </column>
    </row>
    <row>
        <column>
            <name>Month</name>
            <value>3</value>
        </column>
        <column>
            <name>Year</name>
            <value>2010</value>
        </column>
        <column>
            <name>EmpName</name>
            <value>Ned</value>
        </column>
        <column>
            <name>Age</name>
            <value>25</value>
        </column>
    </row>
</resultset>

Ожидаемый вывод:

<Response>
    <PeriodInfo>
        <Month>2</Month>
        <Year>2010</Year>
        <EmployeeDetails>
            <Name>Anu</Name>
            <Age>24</Age>
        </EmployeeDetails>
        <EmployeeDetails>
            <Name>Nancy</Name>
            <Age>26</Age>
        </EmployeeDetails>
    </PeriodInfo>
    <PeriodInfo>
        <Month>3</Month>
        <Year>2010</Year>
        <EmployeeDetails>
            <Name>Ned</Name>
            <Age>25</Age>
        </EmployeeDetails>
    </PeriodInfo>
</Response>

Ответы [ 2 ]

2 голосов
/ 09 января 2011

Определите ключ «строка за месяцем», который индексирует строки по году и месяцу.

Затем используйте мюнхенскую группировку для выбора уникальных комбинаций год-месяц во входных данных. Шаблон «строка» применяется один раз для каждого из них.

Чтобы сгенерировать вывод «EmployeeDetails», используйте key(), чтобы выбрать все строки с тем же годом-месяцем, что и текущая итоговая строка.

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

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

    <xsl:key name="row-by-month" match="row" 
             use="concat(column[name='Year']/value,'-',
                         column[name='Month']/value)" />

    <xsl:template match="resultset">
        <Response>
            <xsl:apply-templates 
                 select="row[generate-id(.) =
                             generate-id(key('row-by-month',
                                             concat(column
                                                      [name='Year']
                                                      /value,
                                                    '-',
                                                    column
                                                      [name='Month']
                                                      /value))[1])]"/>
        </Response>
    </xsl:template>

    <xsl:template match="row">
        <PeriodInfo>
            <Year>
                <xsl:value-of select="column[name='Year']/value"/>
            </Year>
            <Month>
                <xsl:value-of select="column[name='Month']/value"/>
            </Month>
            <xsl:apply-templates select="key('row-by-month',
                                             concat(column
                                                      [name='Year']
                                                      /value,
                                                    '-',
                                                    column
                                                      [name='Month']
                                                      /value))"
                                 mode="details"/>
        </PeriodInfo>
    </xsl:template>

    <xsl:template match="row" mode="details">
        <EmployeeeDetails>
            <Name>
                <xsl:value-of select="column[name='EmpName']/value"/>
            </Name>
            <Age>
                <xsl:value-of select="column[name='Age']/value"/>
            </Age>
        </EmployeeeDetails>
    </xsl:template>


</xsl:stylesheet>
0 голосов
/ 09 января 2011

Вот существенно более читаемый вариант решения @ Lachlan-Roche :

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

 <xsl:key name="kRowByDate" match="row"
  use="concat(column[name='Year']/value,
             '+',
             column[name='Month']/value)"/>

 <xsl:template match="/*">
  <Response>
    <xsl:apply-templates/>
  </Response>
 </xsl:template>

 <xsl:template match=
  "row[generate-id()
        =
         generate-id(key('kRowByDate',
                         concat(column[name='Year']/value,
                                '+',
                                column[name='Month']/value)
                         )[1]
                     )
         ]
  ">
  <xsl:variable name="vMonth" select="column[name='Month']/value"/>
  <xsl:variable name="vYear" select="column[name='Year']/value"/>
  <PeriodInfo>
    <Month><xsl:value-of select="$vMonth"/></Month>
    <Year><xsl:value-of select="$vYear"/></Year>
    <xsl:apply-templates mode="data"
      select="key('kRowByDate', concat($vYear,'+',$vMonth))"/>
  </PeriodInfo>
 </xsl:template>

 <xsl:template match="row"/>

 <xsl:template match="row" mode="data">
  <EmployeeDetails>
   <Name><xsl:value-of select="column[name='EmpName']/value"/></Name>
   <Age><xsl:value-of select="column[name='Age']/value"/></Age>
  </EmployeeDetails>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<resultset>
    <row>
        <column>
            <name>Month</name>
            <value>2</value>
        </column>
        <column>
            <name>Year</name>
            <value>2010</value>
        </column>
        <column>
            <name>EmpName</name>
            <value>Anu</value>
        </column>
        <column>
            <name>Age</name>
            <value>24</value>
        </column>
    </row>
    <row>
        <column>
            <name>Month</name>
            <value>2</value>
        </column>
        <column>
            <name>Year</name>
            <value>2010</value>
        </column>
        <column>
            <name>EmpName</name>
            <value>Nancy</value>
        </column>
        <column>
            <name>Age</name>
            <value>26</value>
        </column>
    </row>
    <row>
        <column>
            <name>Month</name>
            <value>3</value>
        </column>
        <column>
            <name>Year</name>
            <value>2010</value>
        </column>
        <column>
            <name>EmpName</name>
            <value>Ned</value>
        </column>
        <column>
            <name>Age</name>
            <value>25</value>
        </column>
    </row>
</resultset>

желаемый, правильный результат получается :

<Response>
   <PeriodInfo>
      <Month>2</Month>
      <Year>2010</Year>
      <EmployeeDetails>
         <Name>Anu</Name>
         <Age>24</Age>
      </EmployeeDetails>
      <EmployeeDetails>
         <Name>Nancy</Name>
         <Age>26</Age>
      </EmployeeDetails>
   </PeriodInfo>
   <PeriodInfo>
      <Month>3</Month>
      <Year>2010</Year>
      <EmployeeDetails>
         <Name>Ned</Name>
         <Age>25</Age>
      </EmployeeDetails>
   </PeriodInfo>
</Response>
...