#xslt
#xslt
Вопрос:
У меня есть эта таблица поиска xml:
<lookup>
<Codes>
<code>123<code>
</Codes>
<Codes>
<code>321<code>
</Codes>
</lookup>
и документ:
<document>
<header>
<remarks>test</remarks>
</header>
<Line>
<Line-Item>
<code>123</code>
</Line-Item>
<Line-Item>
<code>444</code>
</Line-Item>
<Line-Item>
<code>321</code>
</Line-Item>
</Line>
</document>
Существует возможность проверить коды документов с помощью кодов таблицы поиска, и если код документа = код поиска, удалить строку из документа.
ответ должен быть:
<document>
<header>
<remarks>test</remarks>
</header>
<Line>
<Line-Item>
<code>444</code>
</Line-Item>
</Line>
</document>
Я застрял на xsl: версия таблицы стилей = «1.0».
С наилучшими пожеланиями 🙂
Комментарии:
1. Хороший вопрос, 1. Смотрите мой ответ для полного решения XSLT 1.0, которое корректно работает даже в таких крайних случаях, когда все
Line-Item/code
значения содержатся в таблице поиска.
Ответ №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:variable name="vCodes" select=
"document('file:///c:/temp/LookupDelete.xml')/*/*/code"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"Line-Item[code
= document('file:///c:/temp/LookupDelete.xml')
/*/*/code
]
"/>
<xsl:template match=
"Line[not(Line-Item/code
[not(. = document('file:///c:/temp/LookupDelete.xml')
/*/*/code
)
]
)
]
"/>
</xsl:stylesheet>
при применении к предоставленному XML-документу:
<document>
<header>
<remarks>test</remarks>
</header>
<Line>
<Line-Item>
<code>123</code>
</Line-Item>
<Line-Item>
<code>444</code>
</Line-Item>
<Line-Item>
<code>321</code>
</Line-Item>
</Line>
</document>
выдает желаемый, правильный результат:
<document>
<header>
<remarks>test</remarks>
</header>
<Line>
<Line-Item>
<code>444</code>
</Line-Item>
</Line>
</document>
Если документ такой:
<document>
<header>
<remarks>test</remarks>
</header>
<Line>
<Line-Item>
<code>123</code>
</Line-Item>
<Line-Item>
<code>321</code>
</Line-Item>
<Line-Item>
<code>321</code>
</Line-Item>
</Line>
</document>
затем снова выдается правильный результат (обратите внимание, что ни один Line
элемент вообще не выводится):
<document>
<header>
<remarks>test</remarks>
</header>
</document>
Комментарии:
1. Спасибо за ответ, я искал что-то такое же, как вы написали.
Ответ №2:
<!-- codes of items to exclude from external document -->
<xsl:variable name="lookup-table" select="document('lookup-table.xml')/lookup/Codes/code"/>
<!-- exclude Line-Items with codes from lookup table -->
<xsl:template match="Line-Item[ code = $lookup-table ]"/>
<!--
exclude <Line> elements,
which contains only <Line-Item>'s which will be removed
-->
<xsl:template match="Line[ not(Line-Item[ code != $lookup-table ]) ]"/>
<!-- copy all other items -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl;apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
Комментарии:
1. К сожалению, это решение не работает в XSLT 1.0. Попробуйте его с процессором XSLT 1.0.
Ответ №3:
Эта таблица стилей выдает желаемый результат:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lookup="lookup">
<lookup:lookup>
<Codes>
<code>123</code>
</Codes>
<Codes>
<code>321</code>
</Codes>
</lookup:lookup>
<xsl:variable name="lookup" select="document('')/*/*/Codes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Line">
<xsl:copy>
<xsl:apply-templates select="@* |
node()[not(self::Line-Item[code=$lookup/code])]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Обратите внимание, что таблица поиска включена в таблицу стилей. Его можно легко включить в отдельный документ, если он слишком велик для включения в преобразование.
Комментарии:
1. @lwburk: Я не считаю этот ответ правильным, потому что, когда все
Line-Item/code
значения элементов находятся в таблице поиска, он все равно создаетLine
элемент.2. @Dimitre — Достаточно справедливо, но я пытаюсь представить сценарий, в котором пустой
Line
элемент мог бы иметь значение. Мысли?3. @lwburk: Дело в том, что из трех ответов только ваш генерирует этот пустой
Line
элемент. Я знаю, что даже если бы у нас было большее количество ответов и даже если бы это соотношение было 1000: 1, вы все равно сказали бы, что есть смысл в создании пустогоLine
. Но это не предполагаемое «значение» — я разочарован, обнаружив, что большинство ваших недавних ответов содержат поспешные решения, которые «проще всего сделать, не задумываясь», и что вы избегаете тратить больше времени и создавать более значимые и ценные решения. Я думаю, что у вас есть потенциал для гораздо большего, и я ожидаю увидеть это.4. @Dimitre — Я не утверждаю, что есть какая-то ценность в создании пустого
Line
. Я утверждаю, что это не может иметь значения.5. @lwburk: Создание чистого вывода действительно имеет значение. Могу ли я предположить, что вы думали об исключении пустого
Line
элемента, но сочли это слишком сложным или отнимающим слишком много времени?