Проверка XSLT, является ли следующий тег в данном контексте последним - PullRequest
0 голосов
/ 22 января 2020

Может быть, вы мне поможете: я новичок в XSL и совсем не разработчик. Прошу прощения, если он недостаточно ясен.

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

Проблема: мне нужно проверить, находится ли изображение в конце файла результата xsl: (например, никакие другие элементы, кроме элемента NOTES, не могут следовать), и поскольку существует несколько контекстов, я не смог сделать это правильно.

<xsl:param name="resultfile" select="book/preface||book/appendix|//chapter|//part[not(chapter)]"/>

Вот что такое файл XML выглядит так:

  <preface>
    <dev>
    <p></p>
    <p></p>
    <figure><image></image></figure> <!--needs to be identified-->
  </dev>
  </preface>
  <part>
    <chapter>
      <section1>
        <p></p>
        <p></p>
        <figure><image></image></figure>
      </section1>
      <section1>
        <p></p>
        <p></p>
        <p></p>
        <figure><image></image></figure> <!--needs to be identified-->
    </section1>
      <notes><p></p></notes>
    </chapter>
  </part>
  <part><dev><p></p>
    <figure><image/></figure><!--needs to be identified-->
  </dev></part>
  <appendix><dev><figure><image/></figure>
    <p></p></dev></appendix>
</book>  

То, что я пытался до сих пор:

<xsl:template match="image">
 <xsl:choose>
    <xsl:when test="parent::figure//following::p[name(parent::node())!='notes'][ancestor::node()=$resultfile] 
and not(parent::fig/following::figure[ancestor::node()=$resultfile])">
<xsl:attribute name="type">middle</xsl:attribute></xsl:when>
   <xsl:otherwise>
<xsl:attribute name="type">end</xsl:attribute>
</xsl:otherwise>
        </xsl:choose>
<!--...-->
</xsl:template>
<xsl:template match="image">
   <xsl:choose>
     <xsl:when test="parent::figure//following::p[name(parent::node())!='notes'][name(../$resultfile) ='chapter' ]
       and not(parent::fig/following::figure[name(../$resultfile) ='chapter' ])">
       <xsl:attribute name="type">middle</xsl:attribute></xsl:when>
     <xsl:otherwise>
       <xsl:attribute name="type">end</xsl:attribute>
     </xsl:otherwise>
   </xsl:choose>
   <!--...-->
 </xsl:template>

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

Я был бы очень рад, если бы вы могли мне помочь! Спасибо, Мария

*** В основном использует XSLT 2 с Saxon HE и Saxon PE 9.5, но также интересуется и другими решениями.

Ответы [ 2 ]

0 голосов
/ 24 января 2020

Есть много способов сделать это. В этой таблице стилей используется функция группировки XSLT 2.0+:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:variable name="last-images" as="element()*">
    <xsl:for-each-group select="/descendant::*" 
                        group-ending-with="preface|appendix|chapter|part">
     <xsl:sequence 
      select="current-group()
                [not(ancestor-or-self::notes
                    |self::preface
                    |self::appendix
                    |self::chapter
                    |self::part)]
                [last()]/self::image"/>
    </xsl:for-each-group>
  </xsl:variable> 

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

<xsl:template match="image">
   <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="type">
        <xsl:value-of 
            select="if ($last-images[. is current()]) then 'end' else 'middle'"/>
    </xsl:attribute>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

Вывод:

<book>
   <preface>
      <dev>
         <p/>
         <p/>
         <figure>
            <image type="end"/>
         </figure> 
         <!--needs to be identified-->
      </dev>
  </preface>
  <part>
      <chapter>
         <section1>
            <p/>
            <p/>
            <figure>
               <image type="middle"/>
            </figure>
         </section1>
         <section1>
            <p/>
            <p/>
            <p/>
            <figure>
               <image type="end"/>
            </figure> 
            <!--needs to be identified-->
         </section1>
         <notes>
            <p/>
         </notes>
      </chapter>
  </part>
  <part>
      <dev>
         <p/>
         <figure>
            <image type="end"/>
         </figure>
         <!--needs to be identified-->
      </dev>
   </part>
  <appendix>
      <dev>
         <figure>
            <image type="middle"/>
         </figure>
         <p/>
      </dev>
   </appendix>
</book>

Объяснение : сгруппировать все элементы в порядке документов с каждой группой, заканчивающейся в контейнерах (preface, appendix, chapter и part элементов), затем отфильтруйте эти conatiners и notes элементы и их потомков. Наконец, выберите последний в группе, только если это элемент image.

Обратите внимание: явное использование оси descendant, инструкция xsl:sequence для сохранения идентичности, is оператор.

0 голосов
/ 22 января 2020

В XSLT 3 вы можете использовать совпадение на $resultfile и передавать descendant::*[last()] в качестве параметра туннеля, затем в шаблоне сопоставления image вы можете сравнить . is $tunnel-param для простой проверки, что image является последний потомок, для более сложного случая с notes Я надеюсь, что условие ниже решает проблему:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="resultfile" select="book/preface|book/appendix|//chapter|//part[not(chapter)]"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="$resultfile">
      <xsl:copy>
          <xsl:apply-templates select="@* | node()">
              <xsl:with-param name="last-desc" tunnel="yes" select="descendant::*[last()]"/>
          </xsl:apply-templates>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="image">
      <xsl:param name="context" tunnel="yes"/>
      <xsl:param name="last-desc" tunnel="yes"/>
      <xsl:if test=". is $last-desc or $last-desc[ancestor-or-self::notes][preceding::*[1] is current()]">
          <xsl:comment>identified</xsl:comment>
      </xsl:if>
      <xsl:next-match/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/pPJ9hE4/1

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