XSLT для каждого со сложным состоянием - PullRequest
3 голосов
/ 29 марта 2012

Я преобразую следующий XML для генерации HTML.

XML </p> <pre><code><clause code="section6"> <variable col="1" name="R1C1" row="1">Water</variable> <variable col="2" name="R1C2" row="1">true</variable> <variable col="1" name="R2C1" row="2">Gas</variable> <variable col="2" name="R2C2" row="2"></variable> <variable col="1" name="R3C1" row="3">Petrol</variable> <variable col="2" name="R3C2" row="3">true</variable> <clause>

XSLT </p> <pre><code>1: <xsl:for-each select="$clause/variable[@col='1']"> 2: <xsl:sort select="@row" data-type="number"/> 3: <xsl:variable name="row-id" select="@row"/> 4: <xsl:variable name="row" select="$clause/variable[@row=$row-id]"/> 5: <xsl:if test="$clause/variable[@col='2' and @row=$row-id]='true'"> 6: <xsl:value-of name="row-no" select="concat(position(), ') ')"/> 7: <xsl:value-of select="$clause/variable[@col='1' and @row=$row-id]"/> 8: </xsl:if> 9: </xsl:for-each>

Преобразование работает отлично и показывает результат 1) Вода 3) Бензин

Проблема заключается в порядковом номере. Вы можете видеть условие в строке 5 фильтров, которые имеют только значение 'true' в col 2 и position (), используемые для отображения порядкового номера. У меня не может быть счетчик хода в XLST.

Мне было интересно, могу ли я добавить условие строки 5 с for-each в строке 1. Результат с приведенным выше примером должен быть 1) Вода 2) Патруль Любой совет?

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

Делает ли это то, что вы хотите?

Я делаю выбор для каждого на столбце 2 как истинный.Таким образом, позиция, которая равна тому, где мы находимся в выбранном наборе узлов, будет равна 2, а не 3

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:template match="/">
        <xsl:for-each select="clause/variable[@col='2' and text()='true']">
            <xsl:sort select="@row" data-type="number"/>
            <xsl:variable name="row-id" select="@row"/>
            <xsl:value-of select="concat(position(), ') ')"/>
            <xsl:value-of select="/clause/variable[@col='1' and @row=$row-id]"/>
        </xsl:for-each>        
    </xsl:template>

</xsl:stylesheet>

Хотя я бы, вероятно, использовал шаблоны в предпочтении for-each и использовал current (), чтобынам не нужна переменная id строки:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:template match="/">
        <xsl:apply-templates select="clause/variable[@col='2' and text()='true']">
            <xsl:sort select="@row" data-type="number"/>            
        </xsl:apply-templates>        
    </xsl:template>

    <xsl:template match="clause/variable[@col='2' and text()='true']">
        <xsl:value-of select="concat(position(), ') ')"/>
        <xsl:value-of select="/clause/variable[@col='1' and @row=current()/@row]"/>
    </xsl:template>

</xsl:stylesheet>
2 голосов
/ 29 марта 2012

Не думаю, что вы можете выразить это одним выражением XPath 1.0.

В XSLT 1.0 я буду использовать ключи, и решение станет коротким, элегантным и эффективным :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:key name="kVarCol2" match="variable[@col=2]" use="@row"/>

 <xsl:template match="/*">
    <xsl:for-each select="variable[@col='1'][key('kVarCol2', @row)='true']">
     <xsl:sort select="@row" data-type="number"/>
        <xsl:value-of select="concat('&#xA;', position(), ') ', .)"/>
    </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML (исправлено, чтобы сделать его правильно оформленным):

<clause code="section6">
    <variable col="1" name="R1C1" row="1">Water</variable>
    <variable col="2" name="R1C2" row="1">true</variable>
    <variable col="1" name="R2C1" row="2">Gas</variable>
    <variable col="2" name="R2C2" row="2"></variable>
    <variable col="1" name="R3C1" row="3">Petrol</variable>
    <variable col="2" name="R3C2" row="3">true</variable>
</clause>

желаемый, правильный результат получается :

1) Water
2) Petrol

II. Решение XPath 2.0 (для одного выражения):

for $i in 1 to max(/*/*/@row/xs:integer(.))
  return
       /*/variable[@row eq string($i)]
            [@col eq '1'
           and
             ../variable
                 [@row eq string($i)
                and
                  @col eq '2'
                and
                  . eq 'true'
                 ]
            ]
             /concat('&#xA;', position(), ') ', .)

Когда это выражение XPath 2.0 вычисляется в том же XML-документе (см. Выше), результатом будет та же искомая строка :

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