Как мне подтвердить, что одна последовательность строк является подмножеством другой? - PullRequest
0 голосов
/ 10 ноября 2019

Я не знаю, как определить, является ли один набор строк (xs: string *) подмножеством ссылочного набора строк.

Я предполагал, что операции набора узлов будут работать с xs: string *, но они работают с типом node (), а не с xs: string. Я пробовал и более простую функцию contains (), которая работает только с одиночными строками, а не с последовательностями строк.

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="permitted" select="tokenize('1,2,3,278', ',')"/>

    <xsl:template match="/">
    <html>
        <xsl:apply-templates/>
    </html>

<xsl:template match="experience">
    <xsl:variable name="test" select="tokenize(ids, ', ')"/>

<xsl:if test="count($permitted | $test)=count($permitted)">
        <xsl:copy-of select="."/> 
    </xsl:if>

</xsl:template>

</xsl:stylesheet>

Я получаю это:

Ошибка: требуемый тип элемента документа -сортировщик заказов является узлом ();предоставленное значение имеет тип элемента xs: string

Ответы [ 3 ]

1 голос
/ 10 ноября 2019

Использование :

not($vTest[not(. = $vPermitted)])

Проверка на основе XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vPermitted" as="xs:string*" select="'1', '2', '3', '278'"/>

  <xsl:variable name="vTest1" as="xs:string*" select="'1', '2', '3'"/>
  <xsl:variable name="vTest2" as="xs:string*" select="'1', '2', '3', '4'"/>

  <xsl:template match="/">
    <xsl:sequence select="not($vTest1[not(. = $vPermitted)])"/>
    <xsl:sequence select="not($vTest2[not(. = $vPermitted)])"/>
  </xsl:template>
</xsl:stylesheet>

Когда вышеуказанное преобразование применяется кВ любом XML-документе (не используется) два выражения XPath оцениваются и выводятся их правильные, требуемые результаты :

true false

Примечание :

Точноодно и то же выражение можно использовать даже в XPath 1.0 (XSLT 1.0), где нет понятия последовательности, но вместо этого можно использовать наборы узлов.


Объяснение :

Это « принцип двойного отрицания ». Этот принцип считается законом мышления в классической логике. Принцип был сформулирован Расселом и Уайтхедом в «Теории математики» как теорема логики высказываний в виде:

enter image description here

«Это принцип двойного отрицания, т.е. предложение эквивалентно ложности его отрицания. "


Наиболее оптимальная реализация - близко к O(N)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vPermitted" as="map(xs:string, xs:boolean)" select=
    "map{'1' : true(), '2' : true(), '3' : true(), '278' : true()}"/>

  <xsl:variable name="vTest1" as="xs:string*" select="'1', '2', '3'"/>
  <xsl:variable name="vTest2" as="xs:string*" select="'1', '2', '3', '4'"/>

  <xsl:template match="/">
    <xsl:sequence select="not($vTest1[not($vPermitted(.))])"/>
    <xsl:sequence select="not($vTest2[not($vPermitted(.))])"/>
  </xsl:template>
</xsl:stylesheet>

Когдавышеупомянутое преобразование применяется к любому документу XML (не используется), два выражения XPath оцениваются и их правильные, требуемые результаты выводятся :

true false

В то время как предыдущие выражения (включая выражения вв настоящее время принят ответ) все имеют временную сложность O(M*N), приведенное выше выражение XPath 3.1 использует предварительно заполненное (глобальное / созданное только один раз) map , так что любая проверка, если ключ существует, занимает постоянное время - , поэтому общая временная сложность этого алгоритма составляет O(N)

Здесь мы делаем разумное предположение, что XPathанВ gine используется хорошо оптимизированная реализация карт, например, основанная на хеш-таблицах

0 голосов
/ 11 ноября 2019

Операции над множествами не работают со строками, но операции с последовательностями работают. Ваша попытка:

<xsl:if test="count($permitted | $test)=count($permitted)">

может быть переписана как:

<xsl:if test="deep-equal(distinct-values(($permitted, $test)), $permitted)">
0 голосов
/ 10 ноября 2019

Если вы используете (XPath 2 и более поздние версии) every $s in $test satisfies $s = $permitted, тогда я думаю, что ваша проверка должна работать для последовательностей атомарных значений, таких как строки.

Как альтернатива: count($test) = count($test[. = $permitted])

...