XSLT - 应用 muenchian 分组后计算子节点
XSLT - Counting child nodes after applying muenchian grouping
对于下面的输入 XML,我可以使用 muenchian grouping
方法将所有子 <invoice>
元素分组到适当的 <shippingBill>
元素下。但是,需要在最终输出 XML 中包含 <shippingBill>
个元素的 count
个元素和 <invoice>
个元素。我不知道该怎么做。
输入XML
<bank>
<shippingBills>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>183</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>184</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>172</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>173</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</shippingBill>
</shippingBills>
</bank>
XSL
<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:key name="key-bill" match="shippingBill" use="shippingBillNo"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBills">
<xsl:copy>
<xsl:apply-templates
select="shippingBill[generate-id() = generate-id(key('key-bill', shippingBillNo)[1])]"
mode="group" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBill" mode="group">
<shippingBill>
<xsl:apply-templates select="*[not(self::invoice)]" />
<invoices>
<xsl:apply-templates select="key('key-bill', shippingBillNo)/invoice" />
</invoices>
</shippingBill>
</xsl:template>
</xsl:stylesheet>
最终输出XML需要
已添加 <checkSum>
元素,该元素具有保存相应计数的子元素。
<bank>
<checkSum>
<noOfInvoices>4</noOfInvoices>
<noOfShippingBills>2</noOfShippingBills>
</checkSum>
<shippingBills>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoices>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>183</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>184</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</invoices>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoices>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>172</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>173</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</invoices>
</shippingBill>
</shippingBills>
</bank>
我会这样做:
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="key-bill" match="shippingBill" use="shippingBillNo" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBills">
<xsl:variable name="distinct-bills" select="shippingBill[generate-id() = generate-id(key('key-bill', shippingBillNo)[1])]" />
<checkSum>
<noOfInvoices>
<xsl:value-of select="count(shippingBill/invoice)" />
</noOfInvoices>
<noOfShippingBills>
<xsl:value-of select="count($distinct-bills)" />
</noOfShippingBills>
</checkSum>
<xsl:copy>
<xsl:apply-templates select="$distinct-bills" mode="group" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBill" mode="group">
<shippingBill>
<xsl:apply-templates select="*[not(self::invoice)]" />
<invoices>
<xsl:apply-templates select="key('key-bill', shippingBillNo)/invoice" />
</invoices>
</shippingBill>
</xsl:template>
</xsl:stylesheet>
对于下面的输入 XML,我可以使用 muenchian grouping
方法将所有子 <invoice>
元素分组到适当的 <shippingBill>
元素下。但是,需要在最终输出 XML 中包含 <shippingBill>
个元素的 count
个元素和 <invoice>
个元素。我不知道该怎么做。
输入XML
<bank>
<shippingBills>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>183</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>184</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>172</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>173</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</shippingBill>
</shippingBills>
</bank>
XSL
<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:key name="key-bill" match="shippingBill" use="shippingBillNo"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBills">
<xsl:copy>
<xsl:apply-templates
select="shippingBill[generate-id() = generate-id(key('key-bill', shippingBillNo)[1])]"
mode="group" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBill" mode="group">
<shippingBill>
<xsl:apply-templates select="*[not(self::invoice)]" />
<invoices>
<xsl:apply-templates select="key('key-bill', shippingBillNo)/invoice" />
</invoices>
</shippingBill>
</xsl:template>
</xsl:stylesheet>
最终输出XML需要
已添加 <checkSum>
元素,该元素具有保存相应计数的子元素。
<bank>
<checkSum>
<noOfInvoices>4</noOfInvoices>
<noOfShippingBills>2</noOfShippingBills>
</checkSum>
<shippingBills>
<shippingBill>
<shippingBillNo>5786885</shippingBillNo>
<shippingBillDate>10/02/2016</shippingBillDate>
<LEODate>11/02/2016</LEODate>
<invoices>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>183</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>184</invoiceNo>
<invoiceDate>07/02/2016</invoiceDate>
</invoice>
</invoices>
</shippingBill>
<shippingBill>
<shippingBillNo>3318135</shippingBillNo>
<shippingBillDate>01/10/2015</shippingBillDate>
<LEODate>01/10/2015</LEODate>
<invoices>
<invoice>
<invoiceSerialNo>1</invoiceSerialNo>
<invoiceNo>172</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
<invoice>
<invoiceSerialNo>2</invoiceSerialNo>
<invoiceNo>173</invoiceNo>
<invoiceDate>29/09/2015</invoiceDate>
</invoice>
</invoices>
</shippingBill>
</shippingBills>
</bank>
我会这样做:
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="key-bill" match="shippingBill" use="shippingBillNo" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBills">
<xsl:variable name="distinct-bills" select="shippingBill[generate-id() = generate-id(key('key-bill', shippingBillNo)[1])]" />
<checkSum>
<noOfInvoices>
<xsl:value-of select="count(shippingBill/invoice)" />
</noOfInvoices>
<noOfShippingBills>
<xsl:value-of select="count($distinct-bills)" />
</noOfShippingBills>
</checkSum>
<xsl:copy>
<xsl:apply-templates select="$distinct-bills" mode="group" />
</xsl:copy>
</xsl:template>
<xsl:template match="shippingBill" mode="group">
<shippingBill>
<xsl:apply-templates select="*[not(self::invoice)]" />
<invoices>
<xsl:apply-templates select="key('key-bill', shippingBillNo)/invoice" />
</invoices>
</shippingBill>
</xsl:template>
</xsl:stylesheet>