Чуть более сложная мюнхенская группировка xslt

еще один новичок в xslt здесь. У меня есть проблема, похожая на эту: Применение группировки Muenchian для простой XML с XSLT, но усложненный дополнительным уровнем узлов.

У меня есть этот XML...

<ALLDATA>
  <THIS>
    <ID>datum 1</ID>
    <DATA>datarecord1</DATA>
    <RELATIONSHIPS>
      <rel>
        <relid>rd1</relid>
        <reldata>something</reldata>
      </rel>
    </RELATIONSHIPS>
  </THIS>
  <THIS>
    <ID>datum 1</ID>
    <DATA>datarecord1</DATA>
    <RELATIONSHIPS>
      <rel>
        <relid>rd2</relid>
        <reldata>other</reldata>
      </rel>
    </RELATIONSHIPS>
  </THIS>
  <THIS>
    <ID>rd1</ID>
    <DATA>relrecord1</DATA>
    <RELATIONSHIPS/>
  </THIS>
  <THIS>
    <ID>rd2</ID>
    <DATA>relrecord2</DATA>
    <RELATIONSHIPS/>
  </THIS>
</ALLDATA>

... и хотел бы преобразовать его в ...

<ALLDATA>
  <THIS>
    <ID>datum 1</ID>
    <DATA>datarecord1</DATA>
    <RELATIONSHIPS>
      <rel>
        <relid>rd1</relid>
        <reldata>something</reldata>
      </rel>
      <rel>
        <relid>rd2</relid>
        <reldata>other</reldata>
      </rel>
    </RELATIONSHIPS>
  </THIS>
  <THIS>
    <ID>rd1</ID>
    <DATA>relrecord1</DATA>
    <RELATIONSHIPS/>
  </THIS>
  <THIS>
    <ID>rd2</ID>
    <DATA>relrecord2</DATA>
    <RELATIONSHIPS/>
  </THIS>
</ALLDATA>

Xslt (1.0), который я использую, очевидно, далеко от базы, поэтому я надеялся, что кто-то с большим знанием (привет!) сможет помочь мне правильно :)

Вот бесполезный xslt...

<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:strip-space elements="*"/>

 <xsl:key name="krel" match="THIS" use="ID"/>

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

 <xsl:template match="appex_user/node">
  <xsl:copy>
    <xsl:apply-templates select="THIS[generate-id() = generate-id(key('krel', ID)[1])]" mode="group"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="THIS/RELATIONSHIPS" mode="group">
  <xsl:copy>
   <xsl:copy-of select="RELATIONSHIPS/rel"/>
   <xsl:apply-templates select="key('krel', ID)"/>
  </xsl:copy>
 </xsl:template>

</xsl:stylesheet>

На самом деле - я пробовал всевозможные комбинации, но безрезультатно.


person rosensfole    schedule 25.02.2016    source источник
comment
Что ж, match="appex_user/node" не соответствует ни одному из ваших входных данных.   -  person Martin Honnen    schedule 25.02.2016
comment
На всякий случай, не должен ли DATA быть частью ключа? Даже если ID и DATA должны быть связаны один к одному, может возникнуть ситуация, когда есть элементы THIS с одинаковыми ID, но другие значения DATA. Тогда при запуске таблицы стилей только с ID для ключа потребуется только один из этих элементов DATA, а все остальные с другими значениями будут потеряны. Просто говорю.   -  person xjuice    schedule 25.02.2016
comment
Ах... бит appex_user был из оригинала - я изменил свои теги, чтобы они выглядели более общими, вместо того, чтобы использовать настоящие теги.   -  person rosensfole    schedule 26.02.2016
comment
Ре. тег DATA: да, вы правы, но в моем случае всегда одно и то же.   -  person rosensfole    schedule 26.02.2016


Ответы (1)


Что-то не так с вашим XSLT

Во-первых, у вас есть шаблон, соответствующий «appex_user/node», которого нет в вашем XML. Здесь вам нужно сопоставить корневой элемент «ALLDATA».

Во-вторых, вы используете атрибут «режим» при выборе отдельных элементов THIS. В этом нет ничего плохого, но у вас нет шаблона, соответствующего элементу THIS, который также использует режим. Это означает, что XSLT будет использовать свой шаблон по умолчанию, который не будет выводить элемент THIS, но продолжит сопоставление его дочерних элементов. Я не думаю, что вам действительно нужно использовать «режим» в этом случае.

Теперь у вас есть шаблон, соответствующий RELATIONSHIPS с использованием режима, который будет сопоставлен, но когда вы используете ключ, вы используете его со значением «ID», который будет искать элемент с именем ID как дочерний элемент текущего узла RELATIONSHIPS . Но ID не ребенок. Вы должны использовать выражение ..\ID, чтобы получить узел, который является дочерним по отношению к родителю.

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

<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:strip-space elements="*"/>

 <xsl:key name="krel" match="THIS" use="ID"/>

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

 <xsl:template match="ALLDATA">
  <xsl:copy>
    <xsl:apply-templates select="THIS[generate-id() = generate-id(key('krel', ID)[1])]" />
  </xsl:copy>
 </xsl:template>

 <xsl:template match="THIS/RELATIONSHIPS">
  <xsl:copy>
   <xsl:apply-templates select="key('krel', ../ID)/RELATIONSHIPS/rel"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
person Tim C    schedule 25.02.2016
comment
Спасибо, Тим, выглядит хорошо. Я попробую, когда вернусь на работу на следующей неделе :) - person rosensfole; 26.02.2016
comment
В дополнение к моему предыдущему ответу - это сработало. Еще раз спасибо! - person rosensfole; 29.02.2016