Как объединить отдельные и избыточные данные в один элемент, используя XSLT? - PullRequest
0 голосов
/ 19 января 2011

Следующий ввод:

<Parent>
 <child>
  <e1>ABC1</e1>
  <e2>XYX</e2>
  <e3>4382</e3>
  <e4>summary1</e4>
  <mName>PRICE</mName>
  <mValue>1234000</mValue>
 </child>
 <child>
  <e1>ABC1</e1>
  <e2>XYX</e2>
  <e3>4382</e3>
  <e4>summary1</e4>
  <mName>TYPE</mName>
  <mValue>SPORTS</mValue>
 </child>
 <child>
  <e1>ABC2</e1>
  <e2>QWE</e2>
  <e3>3456</e3>
  <e4>summary2</e4>
  <mName>TYPE</mName>
  <mValue>SEDAN</mValue>
 </child>
</Parent>

Я хочу объединить дочерний элемент таким образом, чтобы он имел как избыточные, так и отдельные элементы. Ниже приводится ожидаемый результат, я не уверен, как этого добиться с помощью XSL, любая помощь приветствуется.

Ожидаемый результат:

<Parent>
 <child>
  <e1>ABC1</e1>
  <e2>XYX</e2>
  <e3>4382</e3>
  <e4>summary</e4>
  <mName>PRICE</mName>
  <mValue>1234000</mValue>
  <mName>TYPE</mName>
  <mValue>SPORTS</mValue>
 </child>
 <child>
  <e1>ABC2</e1>
  <e2>QWE</e2>
  <e3>3456</e3>
  <e4>summary2</e4>
  <mName>TYPE</mName>
  <mValue>SEDAN</mValue>
 </child>
</Parent>

Обновление от комментариев

Все дочерние элементы уникальны идентифицируется элементом 'e1'. Где два дочерние элементы имеют такие же е элементы, они должны быть объединены так есть один ребенок со списком несколько элементов mName и mValue

Ответы [ 3 ]

1 голос
/ 22 января 2011

После долгих исследований и усилий я пришел к более простому подходу, и вот xsl, который дает желаемый результат '

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

    <xsl:key name="Ids" match="Parent/child" use="e1"/>

    <xsl:template match="/Parent">
         <Parent>
            <xsl:for-each select="child[generate-id(.) 
                                        = generate-id(key('Ids', e1)[1])]">
                 <child>
                    <xsl:copy-of select="e1|e2|e3|e4"/>
                     <xsl:for-each select="key('Ids', e1)">
                            <xsl:copy-of select="mName|mValue"/>
                     </xsl:for-each>
                </child >
            </xsl:for-each>
        </Parent>
    </xsl:template>
</xsl:stylesheet>
0 голосов
/ 21 января 2011

Попробуйте это:

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

  <xsl:key name="childindex" match="child" use="e1" />

  <xsl:template match="Parent">
    <xsl:copy>
      <xsl:apply-templates select="child[generate-id() = generate-id(key('childindex', e1)[1])]"/>

    </xsl:copy>
  </xsl:template>

  <xsl:template match="child">
    <xsl:variable name="all" select="key('childindex',e1)" />
    <xsl:copy>
      <xsl:apply-templates select="e1 | e2 | e3 | e4" />
      <xsl:apply-templates select="$all/mValue | $all/mName" />
    </xsl:copy>
  </xsl:template>

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

Существует шаблон, соответствующий дочернему узлу, который находит ВСЕ дочерние элементы с одинаковыми индексами и выводит элементы mValue и mNode всех этих элементов.

Второй дочерний шаблон будет применен ко всем дочерним элементам, которые имеют предшествующий элемент с одинаковыми индексами, и ничего не выводит, удаляя дубликаты.

РЕДАКТИРОВАТЬ: изменил xslt, и измененная версия очень похожа на Тим, отличается только метод заполнения дочернего элемента.

0 голосов
/ 20 января 2011

Это работа для мюнхенской группировки.Вы найдете многочисленные примеры этого в теге XSLT здесь, на StackOverflow.

Я полагаю, что вы говорите, что дочерние элементы уникально идентифицируются элементами e1, e2, e3 и e4 .Если два дочерних элемента имеют одинаковые элементы e , их следует объединить, чтобы был один дочерний со списком из нескольких mName и mValue элементов.

Сначала вам нужно определить ключ, чтобы помочь вам сгруппировать дочерние элементы

<xsl:key 
   name="children" 
   match="child" 
   use="concat(e1, concat('|', concat(e2, concat('|', concat(e3, concat('|', e4))))))"/>

Это создает ключ, который использует конкатенациюдочерние e элементы, которые можно использовать для поиска дочерних элементов.Обратите внимание на использование символа канала | для их объединения.Если какой-либо из ваших элементов может содержать символ конвейера, вам следует изменить его на использование другого символа.

Далее необходимо сопоставить все вхождения первого экземпляра каждого отдельного дочернего элемента * 1033.*.Это делается с помощью этого страшно выглядящего оператора

<xsl:apply-templates 
   select="
     child[generate-id() 
       = generate-id(
         key('children', 
           concat(e1, concat('|', concat(e2, concat('|', concat(e3, concat('|', e4))))))
         )[1])]"/>

т.е. сопоставления child элементов, которые оказываются первым вхождением этого элемента в наш ключ.

Когда у вас естьсопоставив отдельные дочерние узлы, вы можете затем перебрать все другие дочерние узлы с одинаковыми e элементами

<xsl:for-each select="key('children', concat(e1, concat('|', concat(e2, concat('|', concat(e3, concat('|', e4)))))))">

Поместив это в целомдает

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

   <xsl:key name="children" match="child" use="concat(e1, concat('|', concat(e2, concat('|', concat(e3, concat('|', e4))))))"/>

   <xsl:template match="/Parent">
      <xsl:copy>
         <xsl:apply-templates select="child[generate-id() = generate-id(key('children', concat(e1, concat('|', concat(e2, concat('|', concat(e3, concat('|', e4)))))))[1])]"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="child">
      <xsl:copy>
         <xsl:copy-of select="e1|e2|e3|e4" />
         <xsl:for-each select="key('children', concat(e1, concat('|', concat(e2, concat('|', concat(e3, concat('|', e4)))))))">
            <xsl:copy-of select="mName" />
            <xsl:copy-of select="mValue" />
         </xsl:for-each>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

Когда вы применяете это к вашему входному XML, он должен давать желаемый результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...