我最近问了这个问题,但是意识到我没有很清楚地解释它。 我有一个很大的.csv文件(8000+行),由发票组成,每个发票有多行。我将其解析为XML结构,如下所示(简化)。XSLT将大的单个父节点拆分成较小的子节点
输入1 - $ XMLInput
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<invoiceNumber>1</invoiceNumber>
<invoiceText>invoice 1-1</invoiceText>
<position>1<position>
...
</row>
<row>
<invoiceNumber>1</invoiceNumber>
<invoiceText>invoice 1-2</invoiceText>
<position>2<position>
...
</row>
<row>
<invoiceNumber>2</invoiceNumber>
<invoiceText>invoice 2-1</invoiceText>
<position>3<position>
...
</row>
<row>
<invoiceNumber>2</invoiceNumber>
<invoiceText>invoice 2-2</invoiceText>
<position>4<position>
...
</row>
<row>
<invoiceNumber>3</invoiceNumber>
<invoiceText>invoice 3-1</invoiceText>
<position>5<position>
...
</row>
<row>
<invoiceNumber>3</invoiceNumber>
<invoiceText>invoice 3-2</invoiceText>
<position>6<position>
...
</row>
</roow>
输入2 - $ maxBatchSize 描述:中断到下一批次它变得比这个尺寸(常数)
输入较大的后3 - $ listOfInvoices 描述:文档中唯一发票编号的重复变量。例如:
<root>
<row>
<invoiceNumber>1</invoiceNumber>
</row>
<row>
<invoiceNumber>2</invoiceNumber>
</row>
<row>
<invoiceNumber>3</invoiceNumber>
</row>
</root>
为了提高性能时间,我需要组这些元件由invoiceNumber,成批不大于x的每个节点(变量要导入)。从那里我将每批发送到一个子处理器,而不是一次处理整个原始文档。例如,在上面的例子中的XML文档,如果批量大小可能不大于3,我需要以下XML输出:
输出1 - $ XMLOutput
<root>
<batch>
<row>
<invoiceNumber>1</invoiceNumber>
<invoiceText>invoice 1-1</invoiceText>
<position>1<position>
...
</row>
<row>
<invoiceNumber>1</invoiceNumber>
<invoiceText>invoice 1-2</invoiceText>
<position>2<position>
...
</row>
<row>
<invoiceNumber>2</invoiceNumber>
<invoiceText>invoice 2-1</invoiceText>
<position>3<position>
...
</row>
<row>
<invoiceNumber>2</invoiceNumber>
<invoiceText>invoice 2-2</invoiceText>
<position>4<position>
...
</row>
</batch>
<batch>
<row>
<invoiceNumber>3</invoiceNumber>
<invoiceText>invoice 3-1</invoiceText>
<position>5<position>
...
</row>
<row>
<invoiceNumber>3</invoiceNumber>
<invoiceText>invoice 3-2</invoiceText>
<position>6<position>
...
</row>
</batch>
</root>
这是一个要求,即所有发票的行在同一批中发送。我最初的XSLT尝试是低于(2.0),我尝试模拟一个while循环,通过递归调用模板,将发票组附加到当前节点。当达到最大批量时,我递归地调用批处理模板来创建一个新的批处理。我在每次递归调用之间传递发票和批处理计数器。
编辑:感谢肯的帮助我越来越近。我确实需要每次按行数划分发票,而不是明确发票的数量。理论上,如果以下工作,我不知道如何确保发票号码不存在于前面的兄弟节点中。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:variable name="batch-size" select="40" as="xs:integer"/>
<xsl:variable name="input" select="bpws:getVariableData('sortedInvoicesByBU')"/>
<xsl:key name="invoice-lines-by-invoice-number" match="row" use="invoiceNumber4z"/>
<xsl:template match="/">
<xsl:element name="batches">
<!--establish batches from possible non-contiguous invoice numbers-->
<xsl:for-each-group select="$input/*:UPSData/*:row" group-by="(position() - 1) idiv $batch-size">
<xsl:for-each select="distinct-values($input/*:UPSData/*:row/*:invoiceNumber4z)[not(.=preceding-sibling::item)]">
<xsl:element name="UPSData">
<xsl:for-each select="current()">
<xsl:for-each select="key('invoice-lines-by-invoice-number',.,$input)">
<!--copy rows as they are-->
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:for-each-group>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
再次谢谢你。我绝对同意我试图采取一种程序化的方法,并迫使XSLT相应地适应它,只需要开始学习如何用功能语言进行思考。至于为什么我尝试的编程方法不起作用,我会说这是因为这不是它的设计方式。 – rwolters3
现在我想这是你帮助过的两个问题,我一定会下载和学习你的书,看看你是否在我的领域有任何讲座/课程,或者以前的讲座的缓存版本。另外,我写了一个小的错字,我打算说8000或8千条记录,而不是800万,处理时间要快得多。 – rwolters3
我将我的StackOverflow配置文件更新为即将发布的讲座系列或http://www.CraneSoftwrights.com/schedule.htm#calendar提供的信息。 在http://www.CraneSoftwrights.com/links/udemy-ptux-online.htm上,XSLT/XPath上有5个小时的免费流视频讲座,您甚至不需要设置用户名即可只是自由观看。 Udemy拥有可通过http://www.CraneSoftwrights.com/training/ptux/ptux-video.htm页面购买的DVD流媒体版本。两者都有完整答案的练习。独立书没有练习。 –