если с несколькими элементами - PullRequest
1 голос
/ 11 января 2011

Не знаю, как это четко объяснить, поэтому я просто приведу пример: XML-файл:

<root>
  <one>
    <a a="x"/>
    <a a="y"/>
  </one>
  <two>
    <a a="x"/>
    <a a="y"/>
  </two>
</root>

и вот xsl:

    <xsl:template match="/root">
        <xsl:variable name="self" select="."/>

        <xsl:if test="one/a/@a = $self/two/*/a/@a">
          <xsl:text>it works</xsl:text>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Я простохочу, чтобы if работало ...

// edit

Объяснение:

<requirements>
    <bar/><restaurant/>
</requirements>
<offer>
    <bar/></beach><restaurant/><nightclub/>
<offer>

, поэтому я хочу, чтобы 'if' проверил, если все (в этом случае) элементы «требований» удовлетворяются элементами «предложения»

Ответы [ 5 ]

1 голос
/ 11 января 2011

Используйте это выражение XPath 2.0 :

not($requirements[not(name()=$offer/name())])

, где :

$requirements равно /*/requirements/*

и

$offer - это /*/offer/*

, и они сравниваются с XML-документом ниже (по сути, предоставленный плохо сформированный XMLсделал правильно сформированный документ XML):

<t>
    <requirements>
        <bar/>
        <restaurant/>
    </requirements>
    <offer>
        <baz/>
        <beach/>
        <restaurant/>
        <nightclub/>
    </offer>
</t>

Тот же метод для вашей первоначальной задачи:

not(/*/one/a[not(@a = /*/two/a/@a)])

Обратите внимание, что выше-lener XPath 1.0 решение .:)

1 голос
/ 11 января 2011

Эта таблица стилей XSLT 1.0:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kElementByName" match="requirements/*" use="name()"/>
    <xsl:template match="offer[count(*[key('kElementByName',name())])
                               = count(../requirements/*)]">
        <xsl:text>Success!</xsl:text>
    </xsl:template>
</xsl:stylesheet>

С этим входом (правильно сформированным):

<root>
    <requirements>
        <bar/>
        <restaurant/>
    </requirements>
    <offer>
        <bar/>
        <beach/>
        <restaurant/>
        <nightclub/>
    </offer>
</root>

Вывод:

Success!

Примечание : использование xsl:key, потому что функции неявного приведения набора узлов к скалярному принимают только первый узел.

Выражение XPath 2.0:

every $name in /root/requirements/*/name() 
satisfies $name = /root/offer/*/name()
0 голосов
/ 11 января 2011

РЕДАКТИРОВАТЬ

XSLT 1.0 Решение:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="validTest">
    <xsl:for-each select="/*/requirements/*">
        <xsl:value-of select="concat(name(),'+')"/>
    </xsl:for-each>
</xsl:variable>

<xsl:template match="offer">
    <xsl:if test="count(/*/requirements/*) = count(*[
                                    contains($validTest,
                                        concat(name(),'+')
                                        )
                                    ])">
        <xsl:value-of select="concat('#', @id, ' is a valid offer!&#xa;')"/>
    </xsl:if>
</xsl:template>
</xsl:stylesheet>

Применительно к примеру XML:

<root>
  <requirements>
    <bar/><restaurant/>
  </requirements>
  <offer id="1">
    <bar/><beach/><restaurant/><nightclub/>
  </offer>
  <offer id="2">
    <bar/><beach/><nightclub/>
  </offer>
  <offer id="2">
    <beach/><nightclub/><restaurant/>
  </offer>
  <offer id="4">
    <bar/><beach/><restaurant/><nightclub/>
  </offer>
</root>

дает такой результат:

#1 is a valid offer!
#4 is a valid offer!
0 голосов
/ 11 января 2011

Возможно, вы ищете

test = "каждые $ x в $ self / one / xxx удовлетворяет некоторому $ y в $ self / two / yyy удовлетворяет $ x = $ y "

0 голосов
/ 11 января 2011

Возможно это?

<xsl:template match="/root">
    <xsl:variable name="self" select="."/>
    <xsl:variable name="aKey" select="one/a/@a"/>

    <xsl:if test="$self/two/*/a[@a=$aKey]">
      <xsl:text>it works</xsl:text>
    </xsl:if>
</xsl:template>
...