XSLT 如何删除不需要的输出

发布于 2024-11-06 09:25:06 字数 2022 浏览 0 评论 0原文

我有一个 xsl 样式表,给出了所需的内容,除了在标签之外输出的值。有办法去除它们吗?场景是所需的输出是出现多次的发票的总发票金额。每次执行 xslt 时,参数 p1 都包含总计的 InvoiceNumber。下面的代码显示参数 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,他让我走到了这一步。

I have an xsl stylesheet giving just about what is needed, except there are values outputted outside the tags, . Is there a way to remove them? The scenario is that the desired output is a total invoice amount for invoices that appear more than once. Each time the xslt is executed the parameter p1 contains the InvoiceNumber to total. The code below shows that parameter, p1, hardcoded to '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>

Here is the input:

<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>

Here is the output:

<InvoiceAmount>500</InvoiceAmount>137.00351510363.00351511239.50

Here is desired output:

<InvoiceAmount>500</InvoiceAmount>

Also, thank you goes to lwburk who got me this far.

Problem is that the select statement xpath is not picking out the 'CarrierInvoiceAmount'.  This might work though if I can get the path correct.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

知足的幸福 2024-11-13 09:25:07

我没有得到与您发布的相同的结果(仅351510137.00351510363.00351511239.50,所有文本节点),并且我不知道tempvar(未使用)的用途。

由于看起来您需要的只是特定 InvoiceNumberInvoiceAmount 值的总和,因此只需保持简单并忽略其他所有内容即可:

<?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 传递要处理的参数 invoiceNumber,或者您可以根据需要对其进行硬编码(请参阅版本 1)。

注意:如果您更喜欢数字格式,例如 #.00(固定小数)作为总和,那么您也可以使用 format-number(…) 函数

I do not get the same results as you posted (only 351510137.00351510363.00351511239.50, all the text nodes), and I do not know the purpose of tempvar (unused).

Since it appears that all you need is the sum of InvoiceAmount values for a specific InvoiceNumber, just keep it simple and ignore everything else:

<?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> 

You can pass the InvoiceNumber to process via the parameter invoiceNumber, or you can hardcode it if you like (see version 1).

Note: should you prefer a number format like e.g. #.00 (fixed decimals) for the sum, then you can also use the format-number(…) function.

风蛊 2024-11-13 09:25:07

添加

<xsl:template match="text()"/>

应该有帮助。

Adding

<xsl:template match="text()"/>

should help.

安静被遗忘 2024-11-13 09:25:07

此转换

<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. < p>所需的发票编号作为外部/全局参数 $pNum 的值传递到转换。

  2. 我们使用一个键,通过相应的 InvoiceNumber 值对所有 InvoiceAmount 元素进行索引。

  3. 使用该键,我们定义变量 $vInvoiceAmounts,该变量包含所有 InvoiceAmount 元素的节点集,其值对应于 InvoiceNumber 元素与外部参数 $pNum 的值相同。

  4. 我们还定义了一个变量 ($vIdInvAmount1),其中包含第一个这样的 InvoiceAmount 元素的唯一 ID。

  5. 有一个与任何 InvoiceAmount 元素相匹配的模板。它检查匹配的元素是否是节点集 $vInvoiceAmounts 中包含的第一个元素。如果是这样,则使用单个文本节点子节点生成 InvoiceAmount 元素,其值是 $vInvoiceAmounts 中包含的所有 InvoiceAmount 元素的总和。否则什么也不做。

  6. ,还有第二个模板,它匹配任何文本节点并且不执行任何操作(在输出中将其删除),从而有效地覆盖默认 XSLT 处理的不需要的副作用 - 输出不需要的文本。

This transformation:

<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>

when applied on the provided XML file:

<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>

produces exactly the wanted, correct result:

<InvoiceAmount>500</InvoiceAmount>

Explanation:

  1. The wanted invoice number is passed to the transformation as the value of the external/global parameter $pNum .

  2. We use a key that indexes all InvoiceAmount elements by their corresponding InvoiceNumber values.

  3. Using that key we define the variable $vInvoiceAmounts that contains the node-set of all InvoiceAmount elements the value of whose corresponding InvoiceNumber element is the same as the value of the external parameter $pNum.

  4. We also define a variable ($vIdInvAmount1) that contains a unique Id of the first such InvoiceAmount element.

  5. There is a template that matches any InvoiceAmount element. It checks if the matched element is the first of the elements contained in the node-set $vInvoiceAmounts. If so, a InvoiceAmount element is generated with a single text-node child, whose value is the sum of all InvoiceAmount elements contained in $vInvoiceAmounts. Otherwise nothing is done.

  6. Finally, there is a second template that matches any text node and does nothing (deletes it in the output), effectively overriding the unwanted side effect of the default XSLT processing -- the outputting of unwanted text.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文