简体   繁体   中英

Need help xslt 1.0 grouping for mapping stylesheet

Working on a xslt 1.0 stylesheet for mapping of an address service. I have lookup up some of the examples for the Muenchian method for grouping in xslt 1.0, but i still am confused on the xsl:key and nested xsl:for-each loops.

I am only concerned with the InputAddress node-set. There may be multiple (but not always) InputAddress nodesets as part of the parent ValidateRequest node so i need to loop thru all iterations of InputAddress and then perform the mapping to the pertinent elements.

source xml

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:v1="blah" xmlns:v3="blah2">
<soap:Header/>
<soap:Body>
    <v1:validate>
        <ValidateRequest>
            <!--One or more repetitions:-->
            <InputAddress>
                <v3:City>Redmond</v3:City>
                <v3:Territory>
                    <v3:Name>Washington</v3:Name>
                    <FIPSStateAlphaCode>WA</FIPSStateAlphaCode>
                </v3:Territory>
                <v3:PostalCode>98007</v3:PostalCode>
                <v3:Country>
                    <!--Zero or more repetitions:-->
                    <v3:Name>US</v3:Name>
                </v3:Country>
                <v3:FullAddress>123 main street</v3:FullAddress>
                <v3:FullAddress>Ste 200</v3:FullAddress>
            </InputAddress>
            <InputAddress>
                <v3:City>Seattle</v3:City>
                <v3:Territory>
                    <v3:Name>Washington</v3:Name>
                    <FIPSStateAlphaCode>WA</FIPSStateAlphaCode>
                </v3:Territory>
                <v3:PostalCode>98103</v3:PostalCode>
                <v3:Country>
                    <!--Zero or more repetitions:-->
                    <v3:Name>US</v3:Name>
                </v3:Country>
                <v3:FullAddress>987 1st street</v3:FullAddress>
            </InputAddress>
        </ValidateRequest>
    </v1:validate>
</soap:Body>

expected result

    <soap:Body>
    <wsdl:WS_MDM_Address_ValidationRequest>
        <wsdl:WS_MDM_Address_ValidationRequestElement>
            <wsdl:Address_Line1>123 main street</wsdl:Address_Line1>
            <wsdl:Address_Line2>Ste 200</wsdl:Address_Line2>
            <wsdl:City>Redmond</wsdl:City>
            <wsdl:State>WA</wsdl:State>
            <wsdl:Postal_Code>98007</wsdl:Postal_Code>
            <wsdl:Country>US</wsdl:Country>
        </wsdl:WS_MDM_Address_ValidationRequestElement>
        <wsdl:WS_MDM_Address_ValidationRequestElement>
            <wsdl:Address_Line1>987 1st Street</wsdl:Address_Line1>
            <wsdl:City>Seattle</wsdl:City>
            <wsdl:State>WA</wsdl:State>
            <wsdl:Postal_Code>98103</wsdl:Postal_Code>
            <wsdl:Country>US</wsdl:Country>
        </wsdl:WS_MDM_Address_ValidationRequestElement>
    </wsdl:WS_MDM_Address_ValidationRequest>
</soap:Body> 

and my named template snipet after an xsl:choose(not shown):

<xsl:key name="AddressDoctor" match="v3:FullAddress" use="//v3:FullAddress" />
<xsl:variable name="address" select="/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='validate']/ValidateRequest/InputAddress"/>

<xsl:template name="addressdoctor">
    <soap:Envelope>
        <soap:Header>
            <xsl:copy-of select="/*[local-name()='Envelope']/*[local-name()='Header']/*"/>
        </soap:Header>
        <soap:Body>
            <wsdl:WS_MDM_Address_ValidationRequest>

            <xsl:for-each select="key('AddressDoctor', '.')">
                <wsdl:WS_MDM_Address_ValidationRequestElement>
                    <xsl:for-each select="[not($FullAddress = preceding::text()=$FullAddress)]">
                        <xsl:element name="wsdl:{concat('Address_Line',position())}">
                            <xsl:value-of select="."/>
                        </xsl:element>
                    </xsl:for-each>
                    <wsdl:City>
                    <xsl:for-each select="$address/*[local-name()='City']">
                        <xsl:value-of select="$address/*[local-name()='City']"/>
                    </xsl:for-each>
                    </wsdl:City>
                    <wsdl:State>
                        <xsl:value-of select="$address/*[local-name()='Territory']/*[local-name()='FIPSStateAlphaCode']"/>
                    </wsdl:State>
                    <wsdl:Postal_Code>
                        <xsl:value-of select="$address/*[local-name()='PostalCode']"/>
                    </wsdl:Postal_Code>
                    <wsdl:Country>
                        <xsl:value-of select="$address/*[local-name()='Country']/*[local-name()='Name']"/>
                    </wsdl:Country>
                </wsdl:WS_MDM_Address_ValidationRequestElement>
                </xsl:for-each>
            </wsdl:WS_MDM_Address_ValidationRequest>
        </soap:Body>
    </soap:Envelope>
</xsl:template>

Based on the input XML you have provided I don't see that there is a need for any type of grouping. Which is a good thing considering you are working with XSLT 1.0 since grouping can be a bit difficult to get right. You can instead start with a simple identity template and then override a few of the elements to display the output you are looking for.

Here is the XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v1="blah" xmlns:v3="blah2" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <xsl:output method="xml" indent="yes" />

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="ValidateRequest">
    <wsdl:WS_MDM_Address_ValidationRequest>
      <xsl:apply-templates/>
    </wsdl:WS_MDM_Address_ValidationRequest>
  </xsl:template>

  <xsl:template match="InputAddress">
    <wsdl:WS_MDM_Address_ValidationRequestElement>
      <wsdl:Address_Line1>
        <xsl:value-of select="v3:FullAddress[1]"/>
      </wsdl:Address_Line1>
      <xsl:if test="v3:FullAddress[2]">
        <wsdl:Address_Line2>
          <xsl:value-of select="v3:FullAddress[2]"/>
        </wsdl:Address_Line2>
      </xsl:if>
      <wsdl:City>
        <xsl:value-of select="v3:City"/>
      </wsdl:City>
      <wsdl:State>
        <xsl:value-of select="v3:Territory/FIPSStateAlphaCode"/>
      </wsdl:State>
      <wsdl:Postal_Code>
        <xsl:value-of select="v3:PostalCode"/>
      </wsdl:Postal_Code>
      <wsdl:Country>
        <xsl:value-of select="v3:Country/v3:Name"/>
      </wsdl:Country>
    </wsdl:WS_MDM_Address_ValidationRequestElement>
  </xsl:template>

  <xsl:template match="v1:validate">
    <xsl:apply-templates/>
  </xsl:template>

</xsl:stylesheet>

This will produce the output that you are looking for based on the example you provided.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM