Объединение результатов двух наборов узлов приводит к дублированию члена набора

Я использую xslt 1.0, и мне нужно объединение двух переменных, что означает, что я должен использовать функцию набора узлов.

Приведенный ниже тестовый пример создает объединение одного узла с набором, содержащим этот узел. Поскольку A содержит B, операция объединения должна вернуть B. Но я получаю новый набор с дубликатами A.

Если я использую xpath напрямую, union ведет себя так, как ожидалось. Если я использую переменные и функцию набора узлов, я сталкиваюсь с неожиданным случаем. Мой сценарий требует, чтобы я использовал набор узлов. Я максимально упростил тестовый пример.

Это содержимое XML:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <event>
    <id>3</id>
    <eventType>TYPE1</eventType>
  </event>
  <event>
    <id>2</id>
    <eventType>TYPE2</eventType>
    <parent>3</parent>
  </event>
  <event>
    <id>1</id>
    <eventType>TYPE2</eventType>
    <parent>3</parent>
  </event>
</root>

а это xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                xmlns:ext="http://exslt.org/common"
                exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">      

      <xsl:variable name="t2-events">
        <xsl:copy-of 
          select="root/event
                  [eventType = 'TYPE2' and parent = '3']"/>
      </xsl:variable>

      <xsl:variable name="specific-t2">
          <xsl:copy-of 
            select="root/event
                    [eventType = 'TYPE2' and id = '2']"/>        
      </xsl:variable>

      <DEBUG>        

          <results>            
            <xsl:variable name="dummy" 
                          select="root/event
                                  [eventType = 'TYPE2'] 
                                  | 
                                  root/event[id = '2']"/>
            <xsl:variable name="dummy2" 
                          select="ext:node-set($t2-events)
                                | ext:node-set($specific-t2) "/>

            <xsl:comment>Works as expected</xsl:comment>
            <dummy>              
                <xsl:copy-of select="$dummy"/>
            </dummy>
            <dummy2>
              <xsl:comment>There are 3 elements here, where we should have 2</xsl:comment>
                <xsl:copy-of select="$dummy2"/>
             </dummy2>            
          </results>

      </DEBUG>            
    </xsl:template>  
</xsl:stylesheet>

Как применить объединение к двум вызовам node-set()?


person mahonya    schedule 15.08.2013    source источник


Ответы (1)


Я не думаю, что здесь виноват node-set().

Вы определили переменные t2-events и specific-t2 с помощью xsl:copy-of. Таким образом, ваши переменные должны содержать (и содержат) свежие копии (новые узлы элементов) узлов, выбранных выражениями выбора в xsl:copy-of. Из этого следует, что ни один из элементов event в двух переменных не идентичен ни одному из элементов event во входных данных, и аналогичным образом две копии события 2, сделанные в двух переменных, являются двумя копиями, а не двумя ссылками на одну копию.

Обратите внимание, что когда мы добавляем еще несколько переменных в ваш код отладки (кстати, отличная работа по сокращению примера!), объединение происходит, как мы и ожидали, независимо от того, используем ли мы node-set() или нет. (По крайней мере, в xsltproc.)

После ваших первых двух переменных я добавил еще две:

<xsl:variable name="T2-EVENTS" 
              select="root/event
                      [eventType = 'TYPE2' and parent = '3']"/>
<xsl:variable name="SPECIFIC-T2" 
              select="root/event
                      [eventType = 'TYPE2' and id = '2']"/>        

Затем в вашем элементе DEBUG я добавил:

<xsl:variable name="dummy3" 
              select="$T2-EVENTS | $SPECIFIC-T2 "/>
<xsl:variable name="dummy4" 
              select="ext:node-set($T2-EVENTS) 
                    | ext:node-set($SPECIFIC-T2) "/>

а также

<dummy3>
  <xsl:comment>How many here?</xsl:comment>
  <xsl:copy-of select="$dummy3"/>
</dummy3>
<dummy4>
  <xsl:comment>How many here?</xsl:comment>
  <xsl:copy-of select="$dummy4"/>
</dummy4>

Когда я запускаю результирующую таблицу стилей с помощью xsltproc, я получаю два элемента в dummy3 и два в dummy4; вызов node-set() не имел значения.

(Тем не менее, я ничего не вижу в описании функции node-set() на сайте EXSLT, где что-то говорится о том, что node-set() сохраняет или не сохраняет идентичность узла. Так что я бы с осторожностью полагался на него в любом случае.)

person C. M. Sperberg-McQueen    schedule 15.08.2013
comment
Спасибо. Я думаю, это проблема, которая у меня есть: мой исходный код также использует xsl: copy-of. Я буду работать над своим кодом, чтобы увидеть, смогу ли я избавиться от копии. - person mahonya; 15.08.2013