2016-01-08 2 views
0

Мне нужен XSLT 1.0, который преобразует следующий XML.XSLT 1.0 для сортировки и группировки XML

<Record> 
    <Row> 
    <Name>AAA</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>BBB</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
    <Row> 
    <Name>CCC</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>DDD</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
    <Row> 
    <Name>EEE</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>FFF</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
    <Row> 
    <Name>GGG</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>HHH</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
</Record> 

Выход Я ожидаю это:

<Output> 
    <Recordset1> 
    <Record> 
     <Name>AAA</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>CCC</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset1> 
    <Record> 
     <Name>EEE</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>GGG</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset2> 
    <Record> 
     <Name>BBB</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>DDD</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
    <Recordset2> 
    <Record> 
     <Name>FFF</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>HHH</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
</Output> 

условия являются:

  1. Recordset1 должен содержать Surname1 узлам

  2. Recordset2 должен содержать Surname2 узлы

  3. Выход должен быть отсортирован по фамилии

  4. Максимальное количество записей в наборе записей не более 2 записей.

ответ

0

Это может вам помочь.

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxml="urn:schemas-microsoft-com:xslt" 
exclude-result-prefixes="msxml"> 
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 

<xsl:key match="Row" name="rows" use="Surname"/> 

<xsl:template match="Record"> 
    <Output> 
    <xsl:for-each select="Row[generate-id(.) = generate-id(key('rows', Surname)[1])]"> 
     <xsl:sort select="Surname" data-type="text" order="ascending"/> 

     <xsl:variable name="Recordset" select="concat('Recordset',position())"/> 

     <xsl:variable name="Rows"> 
     <xsl:copy-of select="key('rows', Surname)"/> 
     </xsl:variable> 

     <xsl:variable name="RowList" select="msxml:node-set($Rows)"/> 

     <xsl:for-each select="$RowList/Row[position() mod 2 = 1]"> 
     <xsl:element name="{$Recordset}"> 
      <Record> 
      <xsl:copy-of select="./*"/> 
      </Record> 
      <xsl:if test="following-sibling::Row[1]/*"> 
      <Record> 
       <xsl:copy-of select="following-sibling::Row[1]/*"/> 
      </Record> 
      </xsl:if> 
     </xsl:element> 
     </xsl:for-each> 

    </xsl:for-each> 
    </Output> 
</xsl:template> 
</xsl:stylesheet> 
+0

Что на земле вы представляете себе это делает: ' '? –

+1

Это из метода Muenchian, который вы любезно указали мне ранее. Я просто упростил для каждой его части следующее: для каждой строки фамилии найдите первый экземпляр строки с этой фамилией. Итак, если текущий Row - это первый экземпляр, тогда делайте что-нибудь. Отличный вопрос. Кстати, этот код работает очень хорошо. – Bluewood66

+0

"* Для каждой строки фамилии найдите первый экземпляр Row с этой фамилией. *« Это не то, что делает ваше «упрощение». Он находит каждую строку, чье ** полное текстовое значение ** равно текстовому значению первого экземпляра строки с этой фамилией. Это может привести к дублированию. –

0

Существовали несколько трюков на это:

  1. Выберите различные фамилии.
  2. Группируйте записи фамилии.
  3. Подзаголовок записи в группах по 2.
  4. Создание динамических имен элементов на основе отдельного индекса фамилии.

Эта таблица стилей решает эти проблемы:

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

    <xsl:template match="/Record"> 
    <Output> 
     <xsl:apply-templates select="//Row[not(./Surname=preceding::Surname)]/Surname" mode="group"> 
     <xsl:sort select="Surname" /> 
     </xsl:apply-templates> 
    </Output> 
    </xsl:template> 

    <xsl:template match="Surname" mode="group"> 
    <xsl:variable name="surname" select="./text()" /> 
    <xsl:variable name="surnameIndex" select="position()" /> 
    <xsl:variable name="surnameGroup" select="/Record/Row[Surname/text()=$surname]" /> 
    <xsl:for-each select="$surnameGroup"> 
     <xsl:variable name="index" select="position()" /> 
     <!-- only create a new record set on the first (or only) member of the output pair --> 
     <xsl:if test="$index mod 2=1"> <!-- positions are 1 based, not 0 based --> 
     <xsl:element name="Recordset{$surnameIndex}"> 
      <!-- alternatively, use xsl:copy-of --> 
      <xsl:apply-templates select="$surnameGroup[$index]" mode="record" /> 
      <xsl:apply-templates select="$surnameGroup[$index+1]" mode="record" /> 
     </xsl:element> 
     </xsl:if> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="Row" mode="record"> 
    <Record> 
     <Name><xsl:value-of select="Name" /></Name> 
     <Surname><xsl:value-of select="Surname" /></Surname> 
    </Record> 
    </xsl:template> 

</xsl:stylesheet> 

Выход применения этой таблицы стилей против вашего входного документа является:

<?xml version="1.0" encoding="UTF-8" ?> 
<Output> 
    <Recordset1> 
    <Record> 
     <Name>AAA</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>CCC</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset1> 
    <Record> 
     <Name>EEE</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>GGG</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset2> 
    <Record> 
     <Name>BBB</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>DDD</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
    <Recordset2> 
    <Record> 
     <Name>FFF</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>HHH</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
</Output> 
+0

Это не очень хороший ответ - см. Вот почему: http://www.jenitennison.com/xslt/grouping/muenchian.html –

+0

@ michael.hor257k Вы правы, это отличный ответ, потому что он решает данный вопрос, пока разделение различных проблем @ Роланд столкнулся.Если вы обеспокоены тем, что использование 'previous' слишком малоэффективно для определения отдельных значений, тогда в первом шаблоне можно было бы легко заменить другой метод. – vallismortis

Смежные вопросы