XSLT-1.0: объединение и фильтрация двух XML-файлов

#xml #xslt #xpath #xslt-1.0

#xml #xslt #xpath #xslt-1.0

Вопрос:

Мне нужно условно объединить два XML-файла с помощью xslt-1.0. Первый файл:

 <rootnode>
 <section id="1" >
  <outer param="p1" >
   <inner />
   <inner />
  </outer>
  <outer >
   <inner />
  </outer>
  <outer />
  <outer />
 </section>
 <section id="3" >
  <outer >
   <inner />
   <inner />
   <inner />
  </outer>
 </section>
</rootnode>
  

Второй файл:

 $ cat res.xml 
<rootnode>
 <section id="1" status="fail">
  <outer param="p1" status="fail">
   <inner status="fail"/>
   <inner status="pass"/>
  </outer>
  <outer status="pass">
   <inner status="pass"/>
  </outer>
  <outer status="pass"/>
  <outer status="fail"/>
 </section>
 <section id="2" status="fail">
  <outer status="fail">
   <inner status="pass"/>
   <inner status="fail"/>
   <inner status="inc"/>
  </outer>
 </section>
 <section id="6" status="inc">
  <outer status="inc">
   <inner status="inc"/>
  </outer>
 </section>
</rootnode>
  

Пока у меня есть этот файл XSLT:

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

<xsl:param name="doc" select="document('in.xml')"/>

<!-- part 1 -->
<xsl:template match="/">    
  <xsl:variable name="var" select="/rootnode/section" />
  <xsl:for-each select="$doc//section[not(@id = $var/@id)] ">
    <xsl:copy-of select="."/>
  </xsl:for-each>
</xsl:template>

<!-- part 2 -->
<!--xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="*[@status[not(normalize-space()='fail')]]"/>
<xsl:template match="@*[local-name() = 'status' "/-->

</xsl:stylesheet>
  

Я использую xsltproc для обработки файлов

 $ xsltproc filter.xsl res.xml
  

В части 1 будут напечатаны section узлы, которые находятся внутри in.xml , а не внутри res.xml . Если я закомментирую часть 1 и раскомментирую часть 2, я получу узлы, у res.xml которых есть fail статус. Мне как-то нужно объединить эти функции, т. Е. Мне нужно получить все section узлы, которые находятся только в файле in.xml , и, кроме того, все узлы из res.xml этого имеют fail статус. Узлы однозначно идентифицируются по их id атрибуту в section .

Для вышеуказанных двух файлов результирующий файл должен выглядеть следующим образом:

 $ cat final.xml 
<?xml version="1.0" encoding="UTF-8"?>
<rootnode>
  <section id="1">
    <outer param="p1">
      <inner/>
    </outer>
    <outer/>
  </section>
  <section id="2">
    <outer>
      <inner/>
    </outer>
  </section>
  <section id="3">
    <outer>
      <inner/>
      <inner/>
      <inner/>
    </outer>
  </section>
</rootnode>
  

Комментарии:

1. Невозможно объединить два входных файла перед обработкой с помощью xslt? Может быть, это будет проще.

2. После конкатенации вы можете применить группировку и фильтрацию по-мюнхенски. www.jenitennison.com/xslt/grouping/muenchian.html

3. При беглом взгляде оба выглядят как одна и та же структура, причем первая практически не содержит данных. Почему бы просто не преобразовать second для выравнивания по первому?