Создайте таблицу стилей XSL, чтобы исключить ненужные элементы на основе входных параметров - PullRequest
6 голосов
/ 15 октября 2011

Это будет немного длинным и конкретным, поэтому, пожалуйста, потерпите меня.Я понимаю, как работает XSLT, но я не знаю всех элементов, которые выполняют операции.Буду признателен за любую помощь, которую вы можете предоставить.

Допустим, у меня есть пилотное руководство для 737-х, написанное на XML.Тем не менее, есть 3 типа 737 (400, 600 и 800), и хотя 90% руководства одинаковы для всех трех типов, есть определенные детали, которые предназначены только для каждого типа.Некоторые пилоты узнают только о 1 или 2 (или иногда всех 3) самолетах, поэтому я бы хотел пропустить те разделы, которые для них не актуальны.Вот как я настроил XML:

<manual>
    <section>A: This is relevant for every type</section>
    <section t600="no" t800="no">B: This is relevant only for the 737-400</section>
    <section t800="no">C: This is relevant for 737-400 and 737-600</section>
    <section t400="no">D: This is relevant for 737-600 and 737-800</section>
</manual>

Я хочу каким-то образом указать, что меня интересует, скажем, 737-800, и получить руководство, подобное этому:

<manual>
    <section>A: This is relevant for every type</section>
    <section>D: This is relevant for 737-600 and 737-800</section>
</manual>

Или для другого пилота, который заинтересован в двух самолетах, скажем, 737-400 и 737-600, руководство будет выглядеть так:

<manual>
    <section>A: This is relevant for every type</section>
    <section>B: This is relevant only for the 737-400</section>
    <section>C: This is relevant for 737-400 and 737-600</section>
    <section>D: This is relevant for 737-600 and 737-800</section>
</manual>

У меня есть доступ кисходный XML, так что если способ, которым я его настроил, не имеет смысла, я могу изменить его.Я думал так: почти все одинаковы для всех типов, поэтому имеет смысл отказаться, но я понимаю, что это может затруднить сопоставление?Я не уверен.

Еще раз спасибо за взгляд!Дайте мне знать, если я что-то пропустил.

1 Ответ

3 голосов
/ 15 октября 2011

I. Решение XSLT 2.0 :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pInterests">
  <interest topic="t800"/>
 </xsl:param>


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

 <xsl:template match=
  "section[some $t in $pInterests/*/@topic
            satisfies
              not($t = current()/@*[. eq 'no']/name())
          ]
  ">
   <section><xsl:apply-templates/></section>
 </xsl:template>

 <xsl:template match="section"/>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<manual>
    <section>A: This is relevant for every type</section>
    <section t600="no" t800="no">B: This is relevant only for the 737-400</section>
    <section t800="no">C: This is relevant for 737-400 and 737-600</section>
    <section t400="no">D: This is relevant for 737-600 and 737-800</section>
</manual>

дает желаемый, правильный результат :

<manual>
   <section>A: This is relevant for every type</section>
   <section>D: This is relevant for 737-600 and 737-800</section>
</manual>

Если заменить в преобразовании текущий параметр :

 <xsl:param name="pInterests">
  <interest topic="t800"/>
 </xsl:param>

с

 <xsl:param name="pInterests">
  <interest topic="t400"/>
  <interest topic="t600"/>
 </xsl:param>

и снова примените измененное преобразование к тому же XML-документу, мы также получим требуемый и правильный результат :

<manual>
   <section>A: This is relevant for every type</section>
   <section>B: This is relevant only for the 737-400</section>
   <section>C: This is relevant for 737-400 and 737-600</section>
   <section>D: This is relevant for 737-600 and 737-800</section>
</manual>

II. Решение XSLT 1.0 :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pInterests">
  <interest topic="t800"/>
 </xsl:param>

 <xsl:key name="kSectionTypeAttrByName" match="section/@*"
  use="concat(generate-id(..),'|', name())"/>

 <xsl:variable name="vInterests" select=
  "document('')/*/xsl:param[@name='pInterests']/*"/>

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

 <xsl:template match="section">
  <xsl:variable name="vSec" select="."/>

  <xsl:variable name="vHasInterest">
   <xsl:for-each select="$vInterests/@topic">
    <xsl:variable name="vTopic" select="."/>


    <xsl:for-each select=
     "$vSec[not(key('kSectionTypeAttrByName',
                    concat(generate-id(),'|', $vTopic)
                   )
                =
                 'no'
                )
           ]">
      <xsl:text>1</xsl:text>
    </xsl:for-each>

   </xsl:for-each>
  </xsl:variable>

  <xsl:if test="string($vHasInterest)">
   <section><xsl:apply-templates/></section>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<manual>
    <section>A: This is relevant for every type</section>
    <section t600="no" t800="no">B: This is relevant only for the 737-400</section>
    <section t800="no">C: This is relevant for 737-400 and 737-600</section>
    <section t400="no">D: This is relevant for 737-600 and 737-800</section>
</manual>

дает желаемый, правильный результат :

<manual>
   <section>A: This is relevant for every type</section>
   <section>D: This is relevant for 737-600 and 737-800</section>
</manual>

Если заменить в преобразовании текущий параметр :

 <xsl:param name="pInterests">
  <interest topic="t800"/>
 </xsl:param>

с

 <xsl:param name="pInterests">
  <interest topic="t400"/>
  <interest topic="t600"/>
 </xsl:param>

и снова примените измененное преобразование к тому же XML-документу, мы также получим требуемый и правильный результат :

<manual>
   <section>A: This is relevant for every type</section>
   <section>B: This is relevant only for the 737-400</section>
   <section>C: This is relevant for 737-400 and 737-600</section>
   <section>D: This is relevant for 737-600 and 737-800</section>
</manual>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...