#xslt
#xslt
Вопрос:
У меня есть таблица стилей xsl, предоставляющая примерно то, что необходимо, за исключением значений, выводимых вне тегов, . Есть ли способ их удалить? Сценарий заключается в том, что желаемый вывод представляет собой общую сумму счета для счетов, которые отображаются более одного раза. Каждый раз, когда выполняется xslt, параметр p1 содержит значение InvoiceNumber для total. Приведенный ниже код показывает, что параметр p1 жестко запрограммирован на ‘351510’.
<?xml version="1.0" encoding="utf-8"?>
<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:template match="/Invoices/Invoice[InvoiceNumber=351510][1]/InvoiceNumber">
<xsl:copy>
<xsl:apply-templates select="/Invoices/Invoice[InvoiceNumber=351510][1]/InvoiceAmount"/>
</xsl:copy>
</xsl:template>
<xsl:param name="tempvar"/>
<xsl:template name="InvTotal" match="/Invoices/Invoice[InvoiceNumber=351510][1]/InvoiceNumber">
<xsl:variable name="p1" select="351510" />
<xsl:if test="/Invoices/Invoice/InvoiceNumber[. = $p1]">
<!--<xsl:if test="$test = $p1" >-->
<InvoiceAmount>
<xsl:value-of select="sum(../../Invoice[InvoiceNumber=351510]/InvoiceAmount)"/>
</InvoiceAmount>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Вот входные:
<Invoices>
- <Invoice>
<InvoiceNumber>351510</InvoiceNumber>
<InvoiceAmount>137.00</InvoiceAmount>
</Invoice>
- <Invoice>
<InvoiceNumber>351510</InvoiceNumber>
<InvoiceAmount>363.00</InvoiceAmount>
</Invoice>
- <Invoice>
<InvoiceNumber>351511</InvoiceNumber>
<InvoiceAmount>239.50</InvoiceAmount>
</Invoice>
</Invoices>
Вот вывод:
<InvoiceAmount>500</InvoiceAmount>137.00351510363.00351511239.50
Вот желаемый вывод:
<InvoiceAmount>500</InvoiceAmount>
Кроме того, спасибо lwburk, который помог мне зайти так далеко.
Комментарии:
1. Хороший вопрос, 1. Смотрите мой ответ для получения полного, короткого и простого решения и подробного объяснения.
Ответ №1:
Добавление
<xsl:template match="text()"/>
должно помочь.
Комментарии:
1. Я добавил ‘<xsl: template match =»/Invoices/ Инвойс[InvoiceNumber =351510][1]/InvoiceNumber /text()»>’, не уверен, что вы это имели в виду. Спасибо.
Ответ №2:
Я не получаю те же результаты, что вы опубликовали (только 351510137.00351510363.00351511239.50
все текстовые узлы), и я не знаю назначение tempvar
(неиспользуемое).
Поскольку кажется, что все, что вам нужно, это сумма InvoiceAmount
значений для определенного InvoiceNumber
, просто сделайте это простым и игнорируйте все остальное:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="invoiceNumber"/>
<xsl:template match="/">
<InvoiceAmount>
<xsl:value-of select="sum(/Invoices/Invoice[InvoiceNumber=$invoiceNumber]/InvoiceAmount)"/>
</InvoiceAmount>
</xsl:template>
</xsl:stylesheet>
Вы можете передать InvoiceNumber в process через параметр invoiceNumber
, или вы можете жестко закодировать его, если хотите (см. версию 1).
Примечание: если вы предпочитаете числовой формат, такой как, например, #.00
(фиксированные десятичные дроби) для суммы, то вы также можете использовать format-number(…)
функцию.
Комментарии:
1. Я добавил изображение к исходному сообщению, показывающее результаты вашего предложения. При наведении курсора мыши на желтую линию значение равно ‘0’.
2. Если не пространства имен, я подозреваю, что проблема здесь в пробелах: я заметил, что вы использовали,
'351510'
тогда как я использовал351510
(без кавычек). Вы могли бы использоватьnormalize-space(CarrierInvoiceNumber)='351510'
, если вы действительно хотите сохранить кавычки.
Ответ №3:
Это преобразование:
<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:param name="pNum" select="351510"/>
<xsl:key name="kInvAmmtByNumber" match="InvoiceAmount"
use="../InvoiceNumber"/>
<xsl:variable name="vInvoiceAmounts" select=
"key('kInvAmmtByNumber', $pNum)"/>
<xsl:variable name="vIdInvAmount1" select=
"generate-id($vInvoiceAmounts[1])"/>
<xsl:template match="InvoiceAmount">
<xsl:if test="generate-id() = $vIdInvAmount1">
<InvoiceAmount>
<xsl:value-of select="sum($vInvoiceAmounts)"/>
</InvoiceAmount>
</xsl:if>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
при применении к предоставленному XML-файлу:
<Invoices>
<Invoice>
<InvoiceNumber>351510</InvoiceNumber>
<InvoiceAmount>137.50</InvoiceAmount>
</Invoice>
<Invoice>
<InvoiceNumber>351510</InvoiceNumber>
<InvoiceAmount>362.50</InvoiceAmount>
</Invoice>
<Invoice>
<InvoiceNumber>351511</InvoiceNumber>
<InvoiceAmount>239.50</InvoiceAmount>
</Invoice>
</Invoices>
выдает именно желаемый, правильный результат:
<InvoiceAmount>500</InvoiceAmount>
Объяснение:
-
Требуемый номер накладной передается преобразованию в качестве значения внешнего / глобального параметра
$pNum
. -
Мы используем ключ, который индексирует все
InvoiceAmount
элементы по их соответствующимInvoiceNumber
значениям. -
Используя этот ключ, мы определяем переменную,
$vInvoiceAmounts
которая содержит набор узлов всехInvoiceAmount
элементов, значение соответствующегоInvoiceNumber
элемента которого совпадает со значением внешнего параметра$pNum
. -
Мы также определяем переменную (
$vIdInvAmount1
), которая содержит уникальный идентификатор первого такогоInvoiceAmount
элемента. -
Существует шаблон, который соответствует любому
InvoiceAmount
элементу. Он проверяет, является ли соответствующий элемент первым из элементов, содержащихся в наборе узлов$vInvoiceAmounts
. Если это так, тоInvoiceAmount
элемент генерируется с единственным дочерним текстовым узлом, значение которого является суммой всехInvoiceAmount
элементов, содержащихся в$vInvoiceAmounts
. В противном случае ничего не делается. -
Наконец, есть второй шаблон, который соответствует любому текстовому узлу и ничего не делает (удаляет его в выходных данных), эффективно переопределяя нежелательный побочный эффект обработки XSLT по умолчанию — вывод нежелательного текста.