You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

双无界源变量至单无界目标变量的XSLT映射求助

Mapping Two Unbounded Source Elements to a Single Unbounded Target Element

Problem Context

I previously used a for-each to map a single source variable to a target variable, but now need to map two unbounded source elements (Orders and Options) to a single unbounded target element (Details). The goal is to pair each Order with its corresponding Option using the shared OrderID value.

XSD Schema

<?xml version="1.0" encoding="UTF-8"?>
<schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://xmlns.oracle.com/SOATEST/SEQ/SEQBPELProcess" xmlns="http://www.w3.org/2001/XMLSchema">
<element name="Request">
<complexType>
<sequence>
<element name="Orders" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="Name" type="string"/>
<element name="OrderID" type="int"/>
<element name="Qty" type="int"/>
<element name="Price" type="int"/>
</sequence>
</complexType>
</element>
<element name="Options" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="Description" type="string"/>
<element name="catlog" type="string"/>
<element name="Segment" type="string"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
<element name="Response">
<complexType>
<sequence>
<element name="Details" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="OrderID" type="string"/>
<element name="Name" type="string"/>
<element name="Catlog" type="string"/>
<element name="Segment" type="string"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>

Sample Request

<?xml version="1.0" encoding="UTF-8" ?>
<Request xmlns="http://xmlns.oracle.com/SOATEST/SEQ/SEQBPELProcess">
<Orders>
<Name>KIHUN</Name>
<OrderID>101</OrderID>
<Qty>3</Qty>
<Price>4584</Price>
</Orders>
<Orders>
<Name>VENCRI</Name>
<OrderID>102</OrderID>
<Qty>4</Qty>
<Price>98547</Price>
</Orders>
<Options>
<Description>DRONWADRO</Description>
<catlog>EMPTU</catlog>
<Segment>HASBK</Segment>
<OrderID>101</OrderID>
</Options>
<Options>
<Description>WAROAIRDRO</Description>
<catlog>FULLSTC</catlog>
<Segment>UVSS</Segment>
<OrderID>102</OrderID>
</Options>
</Request>

Desired Output

<?xml version = '1.0' encoding = 'UTF-8'?>
<ns0:Response xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns0="http://xmlns.oracle.com/SOATEST/SEQ/SEQBPELProcess">
<ns0:Details>
<ns0:OrderID>101</ns0:OrderID>
<ns0:Name>KIHUN</ns0:Name>
<ns0:Catlog>EMPTU</ns0:Catlog>
<ns0:Segment>HASBK</ns0:Segment>
</ns0:Details>
<ns0:Details>
<ns0:OrderID>102</ns0:OrderID>
<ns0:Name>VENCRI</ns0:Name>
<ns0:Catlog>FULLSTC</ns0:Catlog>
<ns0:Segment>UVSS</ns0:Segment>
</ns0:Details>
</ns0:Response>

Failed Attempt

I tried nesting for-each loops, but this produced incorrect results (a Cartesian product of all Orders and Options):

<ns0:Response>
<xsl:for-each select="/ns0:Request/ns0:Orders">
<xsl:for-each select="/ns0:Request/ns0:Options">
<ns0:Details>
<!-- ... mapping logic ... -->
</ns0:Details>
</xsl:for-each>
</xsl:for-each>
</ns0:Response>

Solution

The issue with nested for-each loops is that they pair every Order with every Option, instead of matching them by OrderID. We can fix this using XSLT keys to index Options by their OrderID, then look up the matching Option for each Order.

Here's the complete XSLT that achieves the desired mapping:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ns0="http://xmlns.oracle.com/SOATEST/SEQ/SEQBPELProcess">
    <xsl:output method="xml" indent="yes"/>

    <!-- Define a key to index Options by their OrderID -->
    <xsl:key name="option-by-orderid" match="ns0:Options" use="ns0:OrderID"/>

    <xsl:template match="/">
        <ns0:Response>
            <!-- Iterate over each Order -->
            <xsl:for-each select="ns0:Request/ns0:Orders">
                <xsl:variable name="current-orderid" select="ns0:OrderID"/>
                <!-- Look up the matching Option using the key -->
                <xsl:variable name="matching-option" select="key('option-by-orderid', $current-orderid)"/>

                <ns0:Details>
                    <ns0:OrderID><xsl:value-of select="$current-orderid"/></ns0:OrderID>
                    <ns0:Name><xsl:value-of select="ns0:Name"/></ns0:Name>
                    <!-- Map Option fields (note the case difference: catlog vs Catlog) -->
                    <ns0:Catlog><xsl:value-of select="$matching-option/ns0:catlog"/></ns0:Catlog>
                    <ns0:Segment><xsl:value-of select="$matching-option/ns0:Segment"/></ns0:Segment>
                </ns0:Details>
            </xsl:for-each>
        </ns0:Response>
    </xsl:template>
</xsl:stylesheet>

Key Explanations:

  1. XSLT Key: The <xsl:key> element creates an index of all Options elements, using their OrderID as the lookup key. This makes it efficient to find the Option that corresponds to a given Order.
  2. Single for-each Loop: Instead of nesting loops, we iterate over each Order once. For each Order, we use the key to fetch the exact matching Option.
  3. Case Sensitivity: Notice that the source has catlog (lowercase 'c') while the target expects Catlog (uppercase 'C')—the XSLT handles this by mapping the source field to the target element name correctly.

This approach ensures each Order is paired with exactly its corresponding Option, producing the expected Details elements.


内容的提问来源于stack exchange,提问作者HKmar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 06:17:37