2010-06-22 2 views
0

В образце XML есть две формы, которые соответствуют по числу и типу; во второй форме соответствия мне нужно вычеркнуть значение элемента flag. Я не могу изменить уровень, который я повторяю из-за некоторых взаимосвязанных таблиц стилей. Я могу сделать preceding-sibling, если бы выполнял итерацию по formslist, но я не могу понять, что синтаксис правильный, если я на один уровень глубже на элементе flag. И число, и тип должны совпадать, прежде чем гасить.previous-sibling с завихрением

<apply-templates match="formslist/flag"> 
<xsl:choose> 
    <xsl:when test=""></xsl:when> 
</xsl:choose> 
</apply-templates> 

Пример XML

<forms> 
    <formslist> 
     <number>one</number> 
     <type>car</type> 
     <flag>da</flag> 
    </formslist> 
    <formslist> 
     <number>two</number> 
     <type>truck</type> 
     <flag>ex</flag> 
    </formslist> 
    <formslist> 
     <number>one</number> 
     <type>car</type> 
     <flag>da</flag> 
    </formslist> 
</forms> 
+0

Ваш вопрос немного запутанный. Если вы хотите получить родитель 'formlist' вашего текущего' флага', вы должны использовать '' .. "'. Для лучшего ответа вам нужно предоставить желаемый результат и полную таблицу стилей. – 2010-06-22 22:16:59

+0

Хороший вопрос (+1). См. Мой ответ для полного и эффективного решения. –

ответ

1

Это преобразование:

<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:key name="kFlag" match="formslist/flag" 
    use="concat(../number, '+', ../type)"/> 

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

<xsl:template match= 
"flag/text()[generate-id(..) 
      != 
      generate-id(key('kFlag', 
          concat(../../number, 
            '+', 
            ../../type 
            ) 
          )[1] 
         ) 
      ] 
"/> 
</xsl:stylesheet> 

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

<forms> 
    <formslist> 
     <number>one</number> 
     <type>car</type> 
     <flag>da</flag> 
    </formslist> 
    <formslist> 
     <number>two</number> 
     <type>truck</type> 
     <flag>ex</flag> 
    </formslist> 
    <formslist> 
     <number>one</number> 
     <type>car</type> 
     <flag>da</flag> 
    </formslist> 
</forms> 

производит разыскиваемого, правильный результат:

<forms> 
    <formslist> 
     <number>one</number> 
     <type>car</type> 
     <flag>da</flag> 
    </formslist> 
    <formslist> 
     <number>two</number> 
     <type>truck</type> 
     <flag>ex</flag> 
    </formslist> 
    <formslist> 
     <number>one</number> 
     <type>car</type> 
     <flag/> 
    </formslist> 
</forms> 

Обратите внимание: использование метода Muenchian для группировки, что значительно быстрее, чем сравнение с preceding-sibling::* (последнее имеет квадратичную производительность O(N^2)).

0

При оценке в матче шаблон для flag это должно выполнить то, что вы ищете:

<xsl:variable name="thisFormslist" select=".." /> 
    <flag> 
     <xsl:choose> 
      <xsl:when test="../preceding-sibling::*[$thisFormslist/number=number and $thisFormslist/type=type]"> 
       <!--number and type have been seen before, so don't put a value for this flag--> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="."/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </flag> 

Это создает переменную для ссылки на текущий formslist и затем использует его в предикатном фильтре для сравнения number и type e preceding-sibling Элементы родительского элемента (formslist).

Смежные вопросы