2011-01-12 2 views
1

Мне нужно преобразовать XML с помощью xslt.Группировка родительского узла на основе значений дочерних элементов и порядкового номера

Логика:

Split родителя, если родитель, имеющий другой адрес ребенка и добавьте порядковый номер с материнским именем. Также нужен номер строки для ребенка. Здесь у нас может быть число родительских узлов, и каждый родительский узел может иметь большее число дочерних узлов.

Я пробовал множество способов достичь этого, и я застрял в генерации порядкового номера в foreach. Так может кто-нибудь попробовать и дать решение для этого.

Источник XML, как показано ниже:

<Data> 
    <Parent> 
     <Name>P1</Name> 
     <Child> 
     <Name>CName1</Name> 
     <Address>Address1</Address> 
     </Child> 
     <Child> 
     <Name>CName2</Name> 
     <Address>Address2</Address> 
     </Child> 
     <Child> 
     <Name>CName3</Name> 
     <Address>Address1</Address> 
     </Child> 
    </Parent> 

    <Parent> 
    <Name>P2</Name> 
     <Child> 
     <Name>CName1</Name> 
     <Address>Address1</Address> 
     </Child> 
    </Parent> 
</Data> 

Мишень XML должен быть, как показано ниже:

<Data> 
    <Parent> 
    <Name>P1_1</Name> 
    <Address>Address1</Address> 
    <Child> 
     <LineNumber>1</LineNumber> 
     <Name>CName1</Name> 
    </Child> 
    <Child> 
     <LineNumber>2</LineNumber> 
     <Name>CName3</Name> 
    </Child> 
    </Parent> 

    <Parent> 
     <Name>P1_2</Name> 
     <Address>Address2</Address> 
     <Child> 
     <LineNumber>1</LineNumber> 
     <Name>CName2</Name> 
     </Child> 
    </Parent> 

    <Parent> 
     <Name>P2_1</Name> 
     <Address>Address1</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName1</Name> 
     </Child> 
    </Parent> 
</Data> 
+0

Пожалуйста, отформатируйте код кнопкой {} – bluish

+0

. Для проблем с группировкой вам действительно нужно рассказать нам, можете ли вы использовать XSLT 2.0 или вы застряли с XSLT 1.0. Группировка * MUCH * проще с 2.0. Кроме того, если вы решили часть проблемы (группировки) и застряли в другой части (нумерация), то полезно показать нам, как далеко вы получили - для этого может потребоваться довольно небольшая настройка, или ваш подход мог бы быть полностью ошибочный. –

ответ

3

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

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

    <xsl:key name="kAddress" match="Child" use="concat(generate-id(..), '|', Address)" /> 

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

    <xsl:template match="Parent"> 
    <xsl:variable name="parent" select="." /> 
    <xsl:for-each select="Child[ 
     generate-id() 
     = 
     generate-id(key('kAddress', concat(generate-id($parent), '|', Address))[1]) 
    ]"> 
     <Parent> 
     <Name><xsl:value-of select="concat(../Name, '_', position())" /></Name> 
     <xsl:copy-of select="Address" /> 
     <xsl:apply-templates select=" 
      key('kAddress', concat(generate-id($parent), '|', Address)) 
     " /> 
     </Parent> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="Child"> 
    <xsl:copy> 
     <xsl:copy-of select="@*" /> 
     <LineNumber><xsl:value-of select="position()" /></LineNumber> 
     <xsl:apply-templates select="node()[not(self::Address)]" /> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

Формирует следующий вывод для вашего образца :

<Data> 
    <Parent> 
     <Name>P1_1</Name> 
     <Address>Address1</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName1</Name> 
     </Child> 
     <Child> 
      <LineNumber>2</LineNumber> 
      <Name>CName3</Name> 
     </Child> 
    </Parent> 
    <Parent> 
     <Name>P1_2</Name> 
     <Address>Address2</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName2</Name> 
     </Child> 
    </Parent> 
    <Parent> 
     <Name>P2_1</Name> 
     <Address>Address1</Address> 
     <Child> 
      <LineNumber>1</LineNumber> 
      <Name>CName1</Name> 
     </Child> 
    </Parent> 
</Data> 
+0

+1 для правильного ответа. –

+0

+1. Все верно. – Flack

+0

+1 Я бы использовал Childs by Parent и Adress только для удобства чтения –

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