Фильтр XSLT, сравнивающий два значения в одном и том же подузле

Мне нужно использовать XSLT (к сожалению, версия 1..), я пытаюсь отфильтровать определенные узлы путем сравнения двух свойств в подузле.

Вот XML:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  </SOAP-ENV:Header>
  <SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <QueriesResponse xmlns="http://schemas.Movies.com/Movies">
      <Films xmlns="http://schemas.Movies.com/Movies">
        <Film>
          <FilmPostings>
            <FilmPosting>
              <FilmPostingDates>
                <FilmPostDate>2017-01-04T19:44:25.9530000-05:00</FilmPostDate>
                <FilmActiveDate>2017-01-04T19:44:25.9530000-05:00</FilmActiveDate>
              </FilmPostingDates>
            </FilmPosting>
          </FilmPostings>
        </Film>
        <Film>
          <FilmPostings>
            <FilmPosting>
              <FilmPostingDates>
                <FilmPostDate>2017-01-04T19:50:06.3830000-05:00</FilmPostDate>
                <FilmActiveDate>2017-01-04T19:50:06.3100000-05:00</FilmActiveDate>
              </FilmPostingDates>
            </FilmPosting>
          </FilmPostings>
        </Film>
        <Film>
          <FilmPostings>
            <FilmPosting>
              <FilmPostingDates>
                <FilmPostDate>2016-12-05T18:03:14.9830000-05:00</FilmPostDate>
                <FilmActiveDate>2017-01-02T00:16:52.7570000-05:00</FilmActiveDate>
              </FilmPostingDates>
            </FilmPosting>
          </FilmPostings>
        </Film>
      </Films>
    </QueriesResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

И вот моя трансформация:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://schemas.Movies.com/Movies"
                xmlns:m="http://schemas.Movies.com/Movies"
                exclude-result-prefixes="m"
                >
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

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

  <!-- This is mean to compare PostDate and ActiveDate, matching if different. It doesn't match any nodes in XML (but should match the final one). -->
  <xsl:template match="m:Film[m:FilmPostings/m:FilmPosting/m:FilmPostingDates/m:FilmPostDate[1] [.!= m:FilmPostings/m:FilmPosting/m:FilmPostingDates/m:FilmActiveDate[1]]]">
  </xsl:template>

  <!-- This code does match the hard coded value (the second node).  -->  
  <!--<xsl:template match="m:Film[m:FilmPostings/m:FilmPosting/m:FilmPostingDates/m:FilmPostDate[1] [.!= '2017-01-04T19:50:06.3830000-05:00']]">    
  </xsl:template>-->

</xsl:stylesheet>

Итак, вы увидите в закомментированном фрагменте, что я могу выполнить сопоставление с жестко закодированными значениями, поэтому я, очевидно, нахожусь в нужной области — я знаю, что код исключит весь узел Film, если он найдет совпадение. . Но сравнение значений двух узлов не работает.

Я пробовал всевозможные варианты в правой части сравнения, но, похоже, он не может подобрать значение ActiveDate.


person NickBeaugié    schedule 09.01.2017    source источник
comment
Можете ли вы подтвердить, какова ваша логика на самом деле? Вы пытаетесь удалить элементы Film, где FilmPostDate и FilmActiveDate равны? Спасибо!   -  person Tim C    schedule 09.01.2017
comment
Да, я. Жестко закодированный пример делает что-то другое, но он только что подтвердил мне, что это, по крайней мере, исключит узел A film.   -  person NickBeaugié    schedule 09.01.2017


Ответы (1)


Чтобы удалить Film элементы, где FilmPostDate и FilmActiveDate вы можете фактически вложить условия в атрибут соответствия

<xsl:template 
     match="m:Film[m:FilmPostings/m:FilmPosting/m:FilmPostingDates[m:FilmPostDate = m:FilmActiveDate]]" />

Это предполагает только один набор элементов FilmPostDate и FilmActiveDate на Film. Если наборов было больше одного, можно попробовать удалить Film элементов, где все вхождения одинаковы (точнее, нет вхождений, которые бы отличались друг от друга).

<xsl:template 
     match="m:Film[not(m:FilmPostings/m:FilmPosting/m:FilmPostingDates[m:FilmPostDate != m:FilmActiveDate])]" />
person Tim C    schedule 09.01.2017
comment
Большое спасибо. Думаю, я недостаточно объяснил о странных требованиях к этой урезанной модели данных. Я знаю, что всегда будет ровно один FilmPosting для каждого элемента Film, и мне все равно, как обрабатывать разные ситуации. - person NickBeaugié; 09.01.2017
comment
Фактический шаблон, который делает то, что мне нужно, выглядит следующим образом: т.е. где значения разные. - person NickBeaugié; 09.01.2017
comment
Теперь я столкнулся с новой проблемой, где во втором узле даты отличаются на миллисекунды. Могу ли я сделать какой-то разбор, чтобы удалить этот компонент из даты? - person NickBeaugié; 09.01.2017
comment
Здесь вы можете использовать некоторую обработку строк. Может быть, просто substring или substring-before, чтобы сделать это. Например substring-before(m:FilmPostDate, '.') = substring-before(m:FilmActiveDate, '.') - person Tim C; 09.01.2017
comment
Это идеально! По какой-то причине я думал, что вы не можете использовать эти функции в матче (в отличие от выбора). Это блестяще. Думаю, теперь у меня есть все, что мне нужно. Большое спасибо за помощь, Тим С! - person NickBeaugié; 09.01.2017