应用程序正在编写XML结构,然后使用XSLT文件对其进行处理,从而生成适合客户端的转换XML(在内存中)。问题在于,虽然合成时间不到一秒钟(行数约为10 000),但转换大约需要30秒。
这是java方法:
StringWriter parsedOutStringWriter = new StringWriter();
StringWriter xmlStringWriter = new StringWriter();
File xsltFile = new File(xslFileProperties.getLocation() + xslFileForProcessing);
JAXBContext jaxbContext = JAXBContext.newInstance(Report.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
jaxbMarshaller.marshal(report, xmlStringWriter);
TransformerFactory transformerFactory = new net.sf.saxon.TransformerFactoryImpl();
Source xsltSource = new StreamSource(xsltFile);
Transformer transformer = transformerFactory.newTransformer(xsltSource);
transformer.setParameter("versionParam", "2.0");
transformer.setParameter("clientType", clientType);
transformer.setParameter("cardType", cardTypeValue);
Source source = new StreamSource(new StringReader(xmlStringWriter.getBuffer().toString()));
Result resultXmlWithFormat = new StreamResult(parsedOutStringWriter);
transformer.transform(source, resultXmlWithFormat);
这是由jaxbMarshaller编组Report.class的XML结构(通常有大约10000 <transaction>
个元素:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<report>
<reportObject>
<object>TEST</object>
<objectValue>111111</objectValue>
</reportObject>
<reportContent>
<reportInterval>
<startDate>2014-07-01T00:00:00+03:00</startDate>
<endDate>2016-09-30T23:59:59.999+03:00</endDate>
</reportInterval>
<client>
<clientId>1111</clientId>
<clientName>Some Client Name</clientName>
<clientTown>-</clientTown>
<clientAddress>-</clientAddress>
</client>
<transaction>
<transactionId>1111111</transactionId>
<transactionBatchId>2016091201111111</transactionBatchId>
<transactionCode>1111111111111111</transactionCode>
<transactionDate>2016-09-12T11:38:49+03:00</transactionDate>
<transactionMain>111</transactionMain>
<transactionAmount>199</transactionAmount>
<transactionACode> </transactionACode>
<transactionBatch>111</transactionBatch>
<transactionBatchDate>2016-09-12T11:40:27+03:00</transactionBatchDate>
<transactionServiceFee>0</transactionServiceFee>
<transactionType>1</transactionType>
<transactionCType>AAAAA</transactionCType>
<transactionCurrency>111</transactionCurrency>
<transactionTerminal>11111111 111</transactionTerminal>
<transactionTId>AA11111</transactionTId>
<transactionClientId>111111</transactionClientId>
<transactionClientName>SOME Client</transactionClientName>
<transactionNetAmount>199</transactionNetAmount>
</transaction>
</reportContent>
</report>
这是转换XSLT文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="fo">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!--<xsl:strip-space elements="*"/>-->
<xsl:decimal-format name="english" decimal-separator="." grouping-separator="," />
<xsl:param name="clientType" />
<xsl:param name="cType" />
<xsl:param name="Interval" />
<xsl:template match="/report">
<report>
<reportObject>
<object>
<xsl:value-of select="reportObject/object"/>
</object>
<objectValue>
<xsl:value-of select="reportObject/objectValue" />
</objectValue>
</reportObject>
<reportContent>
<client>
<clientId>
<xsl:attribute name="type"><xsl:value-of select="$clientType"/></xsl:attribute>
<xsl:value-of select="reportContent/client/clientId"/>
</clientId>
<clientName>
<xsl:value-of select="reportContent/client/clientName" />
</clientName>
<clientTown>
<xsl:value-of select="reportContent/client/clientTown" />
<xsl:if test="reportContent/client/clientTown = ''">-</xsl:if>
</clientTown>
<clientAddress>
<xsl:value-of select="reportContent/client/clientAddress" />
<xsl:if test="reportContent/client/clientAddress = ''">-</xsl:if>
</clientAddress>
</client>
<reportInterval>
<startDate>
<xsl:value-of select="format-dateTime(reportContent/reportInterval/startDate, '[D01].[M01].[Y0001]')"/>
</startDate>
<endDate>
<xsl:value-of select="format-dateTime(reportContent/reportInterval/endDate, '[D01].[M01].[Y0001]')"/>
</endDate>
</reportInterval>
<cardTypes>
<cardType>
<xsl:value-of select="$cType"/>
</cardType>
</cardTypes>
<xsl:for-each-group select="reportContent/transaction" group-by="transactionBatchId">
<xsl:sort select="transactionClientName" />
<xsl:sort select="transactionBatchDate" />
<xsl:sort select="transactionBatch" />
<batch>
<batchDetails>
<batchId>
<xsl:value-of select="transactionBatchId"/>
</batchId>
<batchClientId>
<xsl:value-of select="transactionClientId"/>
</batchClientId>
<batchClientName>
<xsl:value-of select="transactionClientName"/>
</batchClientName>
<batchTransactionTerminal>
<xsl:value-of select="transactionTerminal"/>
</batchTransactionTerminal>
<batchNumber>
<xsl:value-of select="transactionBatch"/>
</batchNumber>
<batchDate>
<xsl:value-of select="format-dateTime(transactionBatchDate,'[D01].[M01].[Y0001]')"/>
</batchDate>
</batchDetails>
<transactionList>
<xsl:for-each select="current-group()">
<xsl:sort select="transactionDate" />
<transaction>
<transactionBatchId>
<xsl:value-of select="transactionBatchId"/>
</transactionBatchId>
<transactionCode>
<xsl:value-of select="transactionCode"/>
</transactionCode>
<transactionDate>
<xsl:value-of select="format-dateTime(transactionDate,'[D01].[M01].[Y0001] [H01]:[m01]:[s01]')" />
</transactionDate>
<transactionMain>
<xsl:value-of select="transactionMain" />
<xsl:if test="transactionMain = ''">-</xsl:if>
</transactionMain>
<transactionACode>
<xsl:value-of select="transactionACode" />
<xsl:if test="transactionACode = ''">-</xsl:if>
</transactionACode>
<transactionAmount>
<xsl:value-of select="format-number(transactionAmount div 100, '#,##0.00', 'english')" />
</transactionAmount>
<transactionServiceFee>
<xsl:value-of select="format-number(transactionServiceFee div 100, '#,##0.00', 'english')" />
</transactionServiceFee>
<transactionNetAmount>
<xsl:value-of select="format-number(transactionNetAmount div 100, '#,##0.00', 'english')" />
</transactionNetAmount >
<transactionCurrency>
<xsl:value-of select="transactionCurrency" />
<xsl:if test="transactionCurrency = ''">-</xsl:if>
</transactionCurrency>
<transactionClientId>
<xsl:value-of select="transactionClientId" />
</transactionClientId>
<transactionBatch>
<xsl:value-of select="transactionBatch" />
</transactionBatch>
<transactionBatchDate>
<xsl:value-of select="format-dateTime(transactionBatchDate,'[D01].[M01].[Y0001]')" />
</transactionBatchDate>
<transactionType>
<xsl:value-of select="transactionType" />
</transactionType>
<transactionCType>
<xsl:value-of select="transactionCType" />
</transactionCType>
</transaction>
</xsl:for-each>
</transactionList>
<!-- batch total -->
<batchTotalItems>
<xsl:value-of select="count(current-group()/transactionAmount)"/>
</batchTotalItems>
<batchTotalAmount>
<xsl:value-of select="format-number(sum(current-group()/transactionAmount) div 100, '#,##0.00', 'english')"/>
</batchTotalAmount>
<batchTotalServiceFee>
<xsl:value-of select="format-number(sum(current-group()/transactionServiceFee) div 100, '#,##0.00', 'english')"/>
</batchTotalServiceFee>
<batchTotalNetAmount>
<xsl:value-of select="format-number(sum(current-group()/transactionNetAmount) div 100, '#,##0.00', 'english')"/>
</batchTotalNetAmount>
</batch>
</xsl:for-each-group>
<!-- overall total -->
<totalItems>
<xsl:value-of select="count(/report/reportContent/transaction/transactionAmount)"/>
</totalItems>
<totalAmount>
<xsl:value-of select="format-number(sum(/report/reportContent/transaction/transactionAmount) div 100, '#,##0.00', 'english')"/>
</totalAmount>
<totalFee>
<xsl:value-of select="format-number(sum(/report/reportContent/transaction/transactionServiceFee) div 100, '#,##0.00', 'english')"/>
</totalFee>
<totalNetAmount>
<xsl:value-of select="format-number(sum(/report/reportContent/transaction/transactionNetAmount) div 100, '#,##0.00', 'english')"/>
</totalNetAmount>
</reportContent>
</report>
</xsl:template>
</xsl:stylesheet>
这就是转换后的XML的样子(通常有大约10000 <transaction>
个元素和相当多的<batch>
个元素:
<report>
<reportObject>
<object>TEST</object>
<objectValue>111111</objectValue>
</reportObject>
<reportContent>
<client>
<clientId type="">111</clientId>
<clientName>Client Name</clientName>
<clientTown>-</clientTown>
<clientAddress>-</clientAddress>
</client>
<reportInterval>
<startDate>01.07.2014</startDate>
<endDate>30.09.2016</endDate>
</reportInterval>
<cardTypes>
<cardType/>
</cardTypes>
<batch>
<batchDetails>
<batchId>2016091201111111</batchId>
<batchClientId>1111111</batchClientId>
<batchClientName>Some Client Name</batchClientName>
<batchTransactionTerminal>11111111A11</batchTransactionTerminal>
<batchNumber>89</batchNumber>
<batchDate>14.04.2016</batchDate>
</batchDetails>
<transactionList>
<transaction>
<transactionBatchId>2016091201111111</transactionBatchId>
<transactionCode>1111111111111111</transactionCode>
<transactionDate>12.09.2016 09:33:52</transactionDate>
<transactionMain>111</transactionMain>
<transactionACode></transactionACode>
<transactionAmount>1.99</transactionAmount>
<transactionServiceFee>0.00</transactionServiceFee>
<transactionNetAmount>1.99</transactionNetAmount>
<transactionCurrency>111</transactionCurrency>
<transactionClientId>1111111</transactionClientId>
<transactionBatch>111</transactionBatch>
<transactionBatchDate>14.04.2016</transactionBatchDate>
<transactionType>1</transactionType>
<transactionCType>AAAAA</transactionCType>
</transaction>
</transactionList>
</batch>
<reportContent>
</report>
有什么方法可以明智地改善这种XSLT性能?或者问题可能在java代码中?注意:模板缓存已经过测试,并没有多大帮助。