如何正确地将<xsl:for-each>与<xsl:result-document>一起使用以输出多个XML文件?

时间:2019-07-11 18:51:44

标签: xml xslt automation xslt-2.0

我希望基于某个节点将一个XML文件转换成多个XML文件,并且XML文件中有多少个XML文件。想要操纵的XML就是这样。

<?xml version="1.0" encoding="utf-8"?>
<PurchaseOrder xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <StoreFrontName>Store front name</StoreFrontName>
    <PurchaseOrderNumber>7291</PurchaseOrderNumber>
    <PurchaseOrderDate>2019-07-09</PurchaseOrderDate>
    <OrdByAddress>
        <Name>First Name Last Nam</Name>
    </OrdByAddress>
    <PurchaseOrderItemDetail id="1">
        <LineNumber>2224</LineNumber>
        <VendorProductID/>
        <VendorProductDescription>Vend Product Desc</VendorProductDescription>
        <CustomerProductID/>
        <CustomerProductDescription>Cust Prod Desc</CustomerProductDescription>
        <OrderQuantity>1</OrderQuantity>
    </PurchaseOrderItemDetail>
    <PurchaseOrderItemDetail id="2">
        <LineNumber>2219</LineNumber>
        <VendorProductID/>
        <VendorProductDescription>Vend Product Desc</VendorProductDescription>
        <CustomerProductID/>
        <CustomerProductDescription>Cust Prod Desc</CustomerProductDescription>
        <OrderQuantity>1</OrderQuantity>
    </PurchaseOrderItemDetail>
    <PurchaseOrderItemDetail id="3">
        <LineNumber>2220</LineNumber>
        <VendorProductID/>
        <VendorProductDescription>Vend Product Desc</VendorProductDescription>
        <CustomerProductID/>
        <CustomerProductDescription>Cust Prod Desc</CustomerProductDescription>
        <OrderQuantity>1</OrderQuantity>
    </PurchaseOrderItemDetail>
    <PurchaseOrderItemDetail id="4">
        <LineNumber>2221</LineNumber>
        <VendorProductID/>
        <VendorProductDescription>Vend Product Desc</VendorProductDescription>
        <CustomerProductID/>
        <CustomerProductDescription>Cust Prod Desc</CustomerProductDescription>
        <OrderQuantity>1</OrderQuantity>
    </PurchaseOrderItemDetail>
    <PurchaseOrderItemDetail id="5">
        <LineNumber>2222</LineNumber>
        <VendorProductID/>
        <VendorProductDescription>Vend Product Desc</VendorProductDescription>
        <CustomerProductID/>
        <CustomerProductDescription>Cust Prod Desc</CustomerProductDescription>
        <OrderQuantity>1</OrderQuantity>
    </PurchaseOrderItemDetail>
    <PurchaseOrderItemDetail id="6">
        <LineNumber>2223</LineNumber>
        <VendorProductID/>
        <VendorProductDescription>Vend Product Desc</VendorProductDescription>
        <CustomerProductID/>
        <CustomerProductDescription>Cust Prod Desc</CustomerProductDescription>
        <OrderQuantity>1</OrderQuantity>
    </PurchaseOrderItemDetail>
</PurchaseOrder>

我的XSLT如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"
        name="xml"/>
    <xsl:template match="PurchaseOrder">
        <xsl:for-each select="PurchaseOrder/PurchaseOrderItemDetail">
            <xsl:result-document format="xml" href="PurchaseOrderItemDetail{position()}.xml" encoding="UTF-8" indent="yes">
                <PurchaseOrderItemDetail>
                    <StorefrontName>
                        <xsl:value-of select="PurchaseOrder/StorefrontName"/>
                    </StorefrontName>
                    <OrderdBy>
                        <xsl:value-of select="OrdByAddress/Name"/>
                    </OrderdBy>
                    <PurchaseOrderNumber>
                        <xsl:value-of select="PurchaseOrder/OrderId"/>
                    </PurchaseOrderNumber>
                    <LineNumber>
                        <xsl:value-of select="PurchaseOrder/PurchaseOrderItemDetail/LineNumber"/>
                    </LineNumber>
                    <PurchaseOrderDate>
                        <xsl:value-of select="PurchaseOrder/OrderDateUtc"/>
                    </PurchaseOrderDate>
                    <OrderQuantity>
                        <xsl:value-of select="PurchaseOrder/PurchaseOrderItemDetail/OrderQuantity"/>
                    </OrderQuantity>
                </PurchaseOrderItemDetail>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

当我尝试使用XMLspear转换XML时,得到的只是用于编码的标签,随后出现一个错误,指出“打开具有给定内容的未格式化源窗格”和LSException:文件的结尾过早。

对于我想要的节点的实际转换,我还尝试了“ copy-of”而不是“ value-of”,但这对我的问题没有影响。

我不确定我缺少什么。

2 个答案:

答案 0 :(得分:0)

for-each内的大多数XPath表达式似乎是错误的,每个PurchaseOrderItemDetail都是for-each内的上下文节点,因此要创建包含以下选定子元素的浅表副本,例如<xsl:copy><xsl:copy-of select="LineNumber, OrderQuantity"/></xsl:copy>,要复制引用来自父代或祖先的孩子的元素,请使用向上到达的路径,例如<xsl:copy><xsl:copy-of select="ancestor::PurchaseOrder/StorefrontName, LineNumber, OrderQuantity"/></xsl:copy>。当然,您也可以创建新元素,但请确保使用正确的路径来选择值。

答案 1 :(得分:0)

对于LineNumberOrderQuantity,您可以进行<xsl:copy-of select="LineNumber"/>等。

对于StoreFrontNamePurchaseOrderNumber,您可以进行<xsl:copy-of select="/*/PurchaseOrderNumber"/>等。

在大多数情况下,您的错误是上下文错误:您需要考虑哪个元素是上下文节点,并确保路径从此处开始。

在其他情况下,您只是不小心命名,例如StoreFrontName的大写是错误的,并且没有名为OrderId的元素。