我遇到了xslt的问题,并且不知道如何将下面的XML转换为所需的输出。 如何根据条件读取相似节点的元素并在同一行生成输出? 此外,O / P文件具有预定义的格式。
XML
<?xml version="1.0" encoding="UTF-8"?>
<Plan Id="01">
<Ledger>1</Ledger>
<Product>PRD-AAA</Product>
<Order_Amount>2480</Order_Amount>
<Invoice_Amount>496</Invoice_Amount>
</Plan>
<Plan Id="02">
<Ledger>2</Ledger>
<Product>PRD-BBB</Product>
<Order_Amount>9000</Order_Amount>
<Invoice_Amount>3000</Invoice_Amount>
</Plan>
<Plan Id="03">
<Product Id="PRD-X">
<Ledger>1</Ledger>
<Order_Amount>4500</Order_Amount>
<Invoice_Amount>1650</Invoice_Amount>
</Product>
<Product Id="PRD-Y">
<Ledger>1</Ledger>
<Order_Amount>550</Order_Amount>
<Invoice_Amount>866</Invoice_Amount>
</Product>
<Product Id="PRD-Z">
<Ledger>2</Ledger>
<Order_Amount>5000</Order_Amount>
<Invoice_Amount>1000</Invoice_Amount>
</Product>
<Product Id="PRD-A">
<Ledger>3</Ledger>
<Order_Amount>2500</Order_Amount>
<Invoice_Amount>1000</Invoice_Amount>
</Product>
</Plan>
CSV文件的列 (无需打印列标题)这只是为了理解O / P文件格式。
Plan Details,Plan ID,Ledger#,Product Code,Amounts,Order Amount,Invoice Amount,STATICTEXTFILLER1,STATICTEXTFILLER2,,Plan ID,Ledger#,Product Code,Amounts,Order Amount,Invoice Amount,STATICTEXTFILLER3
规则: 1)STATICTEXTFILLER1,STATICTEXTFILLER2将在第一张发票金额后出现
2)STATICTEXTFILLER13位于最后一个发票金额的末尾
3)如果计划03只有一个产品在Ledger#中,文件的其余细节应该留空,除了STATICTEXTFILLER1,STATICTEXTFILLER3,STATICTEXTFILLER3
预期输出
Plan Details,01,1,PRD-AAA,Amounts,2480,496,STATICTEXTFILLER1,STATICTEXTFILLER2,,,,Amounts,,,STATICTEXTFILLER3
Plan Details,02,2,PRD-BBB,Amounts,9000,3000,STATICTEXTFILLER1,STATICTEXTFILLER2,,,,Amounts,,,STATICTEXTFILLER3
Plan Details,03,1,PRD-X,Amounts,4500,1650,STATICTEXTFILLER1,STATICTEXTFILLER2,03,1,PRD-Y,Amounts,550,866,STATICTEXTFILLER3
Plan Details,03,2,PRD-Z,Amounts,5000,1000,STATICTEXTFILLER1,STATICTEXTFILLER2,,,,Amounts,,,STATICTEXTFILLER3
Plan Details,03,3,PRD-A,Amounts,2500,1000,STATICTEXTFILLER1,STATICTEXTFILLER2,,,,Amounts,,,STATICTEXTFILLER3
答案 0 :(得分:2)
计划03只有3个计划有多个产品。计划01 而计划02将始终只有一个产品。
这是组织数据的一种奇怪方式。无论如何,请尝试以下方法:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:key name="product3-by-ledger" match="Plan[@Id='03']/Product" use="Ledger" />
<xsl:variable name="LF" select="'
'" />
<xsl:variable name="delim" select="','" />
<xsl:template match="/">
<!-- Plans 01 & 02 -->
<xsl:for-each select="Report_Data/Plan[@Id='01' or @Id='02']">
<xsl:value-of select="concat(@Id, $delim, Ledger, $delim, Product, $delim, Order_Amount, $delim, Invoice_Amount, $LF)"/>
</xsl:for-each>
<!-- Plan 03 -->
<!-- for each distinct ledger -->
<xsl:for-each select="/Report_Data/Plan[@Id='03']/Product[count(. | key('product3-by-ledger', Ledger)[1]) = 1]">
<!--get products with same ledger -->
<xsl:for-each select="key('product3-by-ledger', Ledger)">
<xsl:value-of select="concat(../@Id, $delim, Ledger, $delim, @Id, $delim, Order_Amount, $delim, Invoice_Amount)"/>
</xsl:for-each>
<xsl:if test="position()!=last()">
<xsl:value-of select="$LF"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
修改强>
如果您使用的是XSLT 2.0,请按照其他答案中的建议使用<xsl:for-each-group>
,而不是Muenchian分组。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:key name="product3-by-ledger" match="Plan[@Id='03']/Product" use="Ledger" />
<xsl:variable name="LF" select="'
'" />
<xsl:variable name="delim" select="','" />
<xsl:template match="/">
<!-- Plans 01 & 02 -->
<xsl:for-each select="Report_Data/Plan[@Id='01' or @Id='02']">
<xsl:value-of select="concat(@Id, $delim, Ledger, $delim, Product, $delim, Order_Amount, $delim, Invoice_Amount, $delim, 'STATICTEXTFILLER1,STATICTEXTFILLER2,STATICTEXTFILLER3', $LF)"/>
</xsl:for-each>
<!-- Plan 03 -->
<!-- for each distinct ledger -->
<xsl:for-each select="/Report_Data/Plan[@Id='03']/Product[count(. | key('product3-by-ledger', Ledger)[1]) = 1]">
<!--get products with same ledger -->
<xsl:for-each select="key('product3-by-ledger', Ledger)">
<xsl:value-of select="concat(../@Id, $delim, Ledger, $delim, @Id, $delim, Order_Amount, $delim, Invoice_Amount, $delim)"/>
<xsl:if test="position()=1">
<xsl:text>STATICTEXTFILLER1,STATICTEXTFILLER2,</xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text>STATICTEXTFILLER3</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="position()!=last()">
<xsl:value-of select="$LF"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
以上样式表应用于更正后的输入:
<Report_Data>
<Plan Id="01">
<Ledger>1</Ledger>
<Product>PRD-AAA</Product>
<Order_Amount>2480</Order_Amount>
<Invoice_Amount>496</Invoice_Amount>
</Plan>
<Plan Id="02">
<Ledger>2</Ledger>
<Product>PRD-BBB</Product>
<Order_Amount>9000</Order_Amount>
<Invoice_Amount>3000</Invoice_Amount>
</Plan>
<Plan Id="03">
<Product Id="PRD-X">
<Ledger>1</Ledger>
<Order_Amount>4500</Order_Amount>
<Invoice_Amount>1650</Invoice_Amount>
</Product>
<Product Id="PRD-Y">
<Ledger>1</Ledger>
<Order_Amount>550</Order_Amount>
<Invoice_Amount>866</Invoice_Amount>
</Product>
<Product Id="PRD-Z">
<Ledger>2</Ledger>
<Order_Amount>5000</Order_Amount>
<Invoice_Amount>1000</Invoice_Amount>
</Product>
<Product Id="PRD-A">
<Ledger>3</Ledger>
<Order_Amount>2500</Order_Amount>
<Invoice_Amount>1000</Invoice_Amount>
</Product>
</Plan>
</Report_Data>
将产生:
01,1,PRD-AAA,2480,496,STATICTEXTFILLER1,STATICTEXTFILLER2,STATICTEXTFILLER3
02,2,PRD-BBB,9000,3000,STATICTEXTFILLER1,STATICTEXTFILLER2,STATICTEXTFILLER3
03,1,PRD-X,4500,1650,STATICTEXTFILLER1,STATICTEXTFILLER2,03,1,PRD-Y,550,866,STATICTEXTFILLER3
03,2,PRD-Z,5000,1000,STATICTEXTFILLER1,STATICTEXTFILLER2,STATICTEXTFILLER3
03,3,PRD-A,2500,1000,STATICTEXTFILLER1,STATICTEXTFILLER2,STATICTEXTFILLER3
答案 1 :(得分:1)
你的来源没有根元素,所以我选择了:
修改:更新了评论
中提到的根元素<?xml version="1.0" encoding="UTF-8"?>
<Report_Data>
<Plan Id="01">
<Ledger>1</Ledger>
<Product>PRD-AAA</Product>
<Order_Amount>2480</Order_Amount>
<Invoice_Amount>496</Invoice_Amount>
</Plan>
<Plan Id="02">
<Ledger>2</Ledger>
<Product>PRD-BBB</Product>
<Order_Amount>9000</Order_Amount>
<Invoice_Amount>3000</Invoice_Amount>
</Plan>
<Plan Id="03">
<Product Id="PRD-X">
<Ledger>1</Ledger>
<Order_Amount>4500</Order_Amount>
<Invoice_Amount>1650</Invoice_Amount>
</Product>
<Product Id="PRD-Y">
<Ledger>1</Ledger>
<Order_Amount>550</Order_Amount>
<Invoice_Amount>866</Invoice_Amount>
</Product>
<Product Id="PRD-Z">
<Ledger>2</Ledger>
<Order_Amount>5000</Order_Amount>
<Invoice_Amount>1000</Invoice_Amount>
</Product>
<Product Id="PRD-A">
<Ledger>3</Ledger>
<Order_Amount>2500</Order_Amount>
<Invoice_Amount>1000</Invoice_Amount>
</Product>
</Plan>
</Report_Data>
有了这个:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output method="text"/>
<xsl:template match="Report_Data">
<xsl:apply-templates select="Plan"/>
</xsl:template>
<xsl:template match="Plan">
<xsl:choose>
<!-- Plan type 1, Id 1 and 2 -->
<xsl:when test="not(Product/@Id)">
<xsl:value-of select="@Id,Ledger,Product,Order_Amount,Invoice_Amount" separator=","/>
<xsl:text>
</xsl:text>
</xsl:when>
<!-- Plan type 2, Id 3-->
<xsl:otherwise>
<xsl:for-each-group select="Product" group-by="Ledger">
<xsl:value-of
select="for $i in current-group() return ($i/../@Id,$i/Ledger,$i/@Id,$i/Order_Amount,$i/Invoice_Amount)"
separator=","/>
<xsl:text>
</xsl:text>
</xsl:for-each-group>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
我明白了:
01,1,PRD-AAA,2480,496
02,2,PRD-BBB,9000,3000
03,1,PRD-X,4500,1650,03,1,PRD-Y,550,866
03,2,PRD-Z,5000,1000
03,3,PRD-A,2500,1000
基本上value-of's
根据您的计划类型选择要显示的顺序中的元素序列。使用xslt-2.0,您可以自己保存分隔符并使用值的seprartor属性。