Я пытаюсь напечатать названия фруктов, которых нет в data:fruit
. В моем случае я ожидаю Pineapple, Kiwi
. Я получаю доступ к data:fruit
в конфигурации XSLT xml с помощью 'select = "document('')/*/data:fruit/attribute/@value"'
. В настоящее время я получаю следующую ошибку.
Ошибка:
Error executing XSLT at line 24 : Exception thrown by URIResolver resolving `` against `'. Found while atomizing the first argument of fn:string-join()
Пожалуйста, проверьте следующую ссылку xsltfiddle: https://xsltfiddle.liberty-development.net/jyfAiC7/4
xsl
<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:exsl = "http://exslt.org/common"
xmlns:set = "http://exslt.org/sets"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
extension-element-prefixes = "exsl"
version = "2.0">
<xsl:output method = "xml" indent = "yes" encoding = "UTF-8"/>
<data:fruit>
<attribute value = "Pineapple" />
<attribute value = "Kiwi" />
<attribute value = "Apple" />
<attribute value = "Orange" />
<attribute value = "Banana" />
<attribute value = "Cherry" />
<attribute value = "Peach" />
</data:fruit>
<xsl:template match = "/">
<xsl:variable name = "fruitMissing">
<xsl:for-each select = "document('')/*/data:fruit/attribute/@value">
<xsl:variable name = "fruit" select = "."/>
<xsl:if test = "count(//root/details/item/line[contains(.,$fruit)])=0"><xsl:value-of select = "."/>,</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select = "$fruitMissing"/>
</xsl:template>
</xsl:stylesheet>
XML
<?xml version = "1.0" encoding = "ISO-8859-1"?>
<root>
<header/>
<details>
<item>
<line>14.04.22 5:04:30;Apple;Finished</line>
</item>
<item>
<line>14.04.22 3:36:42;Apple;Finished</line>
</item>
<item>
<line>14.04.22 4:03:47;Orange;Finished</line>
</item>
<item>
<line>14.04.22 2:40:33;Orange;Finished</line>
</item>
<item>
<line>14.04.22 3:37:12;Banana;Finished</line>
</item>
<item>
<line>14.04.22 3:36:59;Cherry;Finished</line>
</item>
<item>
<line>14.04.22 3:36:57;Peach;Finished</line>
</item>
</details>
<summary/>
<statistics/>
<exceptions/>
</root>
Попробуйте это XSLT2:
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:exsl = "http://exslt.org/common"
xmlns:set = "http://exslt.org/sets"
xmlns:data = "http://mulocal/host"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
extension-element-prefixes = "exsl"
version = "2.0">
<xsl:output method = "xml" indent = "yes" encoding = "UTF-8"/>
<data:fruit>
<attribute value = "Pineapple" />
<attribute value = "Kiwi" />
<attribute value = "Apple" />
<attribute value = "Orange" />
<attribute value = "Banana" />
<attribute value = "Cherry" />
<attribute value = "Peach" />
</data:fruit>
<xsl:template match = "/">
<xsl:variable name = "varInput" select = "root"/>
<xsl:for-each select = "document('')/*/data:fruit/attribute/@value">
<xsl:variable name = "fruit" select = "."/>
<xsl:if test = "count($varInput/details/item/line[contains(.,$fruit)])=0">
<xsl:value-of select = "."/><xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Результат:
<?xml version = "1.0" encoding = "UTF-8"?>Pineapple,Kiwi,
Входной XML <root> под всеми узлами будет храниться в этой переменной, и ему необходимо хранить все элементы (узлы) в этой переменной, поэтому они должны храниться снаружи для каждого.
Я бы предложил вам сделать это следующим образом:
XSLT 2.0
<xsl:stylesheet version = "2.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text" encoding = "UTF-8"/>
<xsl:key name = "existing-fruit" match = "item" use = "tokenize(line, ';')[2]" />
<xsl:variable name = "fruit">
<attribute value = "Pineapple" />
<attribute value = "Kiwi" />
<attribute value = "Apple" />
<attribute value = "Orange" />
<attribute value = "Banana" />
<attribute value = "Cherry" />
<attribute value = "Peach" />
</xsl:variable>
<xsl:template match = "/" >
<xsl:variable name = "xml" select = "." />
<xsl:value-of select = "$fruit/attribute[not(key('existing-fruit', @value, $xml))]/@value" separator = ","/>
</xsl:template>
</xsl:stylesheet>
Помимо того, что он короче и эффективнее, он также позволяет избежать возможного ложного срабатывания для других значений, включенных в line
.
Демо: https://xsltfiddle.liberty-development.net/jyfAiC7/5
Сэр, отличное предложение, плюс один, сэр...
@ michael.hor257k: Спасибо за ответ. Можно ли распечатать ключ existing-fruit
. Я хотел бы увидеть содержимое ключа?
Я не уверен, что вы подразумеваете под "содержимое ключа". Вы можете распечатать список фруктов через запятую во входном XML, используя <xsl:value-of select = "/root/details/item/tokenize(line, ';')[2]" separator = ","/>
.
Спасибо за ваш ответ: Могу я спросить вас, что означает root? select = "root" ... А почему вы не поставили закрывающий тег переменной
<xsl:variable name = "varInput" select = "root"/>
после</xsl:for-each>
лайка</xsl:for-each></xsl:variable>