Группировка родительского узла на основе значений дочерних элементов и порядкового номера - PullRequest
1 голос
/ 12 января 2011

Мне нужно преобразовать XML с помощью xslt.

Логика:

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

Я пробовал множество способов добиться этого, и я застрял с созданием порядкового номера в 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>

1 Ответ

3 голосов
/ 12 января 2011

Это преобразование 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...