XSLT как удалить нежелательный вывод

#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, который помог мне зайти так далеко.

Проблема в том, что оператор выбора xpath не выбирает 'CarrierInvoiceAmount'. Это может сработать, хотя, если я смогу указать правильный путь.

Комментарии:

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>
  

Объяснение:

  1. Требуемый номер накладной передается преобразованию в качестве значения внешнего / глобального параметра $pNum .

  2. Мы используем ключ, который индексирует все InvoiceAmount элементы по их соответствующим InvoiceNumber значениям.

  3. Используя этот ключ, мы определяем переменную, $vInvoiceAmounts которая содержит набор узлов всех InvoiceAmount элементов, значение соответствующего InvoiceNumber элемента которого совпадает со значением внешнего параметра $pNum .

  4. Мы также определяем переменную ( $vIdInvAmount1 ), которая содержит уникальный идентификатор первого такого InvoiceAmount элемента.

  5. Существует шаблон, который соответствует любому InvoiceAmount элементу. Он проверяет, является ли соответствующий элемент первым из элементов, содержащихся в наборе узлов $vInvoiceAmounts . Если это так, то InvoiceAmount элемент генерируется с единственным дочерним текстовым узлом, значение которого является суммой всех InvoiceAmount элементов, содержащихся в $vInvoiceAmounts . В противном случае ничего не делается.

  6. Наконец, есть второй шаблон, который соответствует любому текстовому узлу и ничего не делает (удаляет его в выходных данных), эффективно переопределяя нежелательный побочный эффект обработки XSLT по умолчанию — вывод нежелательного текста.