1

New to xslt so please bear with me. I'm attempting to tranform one xml document to another. I specifically need to use a node's value as a selection criteria for another node but am unsure how to do so. This would be analogous to a joining one table to another using foreign keys in SQL.

Source xml:

<?xml version="1.0" encoding="utf-8" ?>
<AbleCommerceExport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Store>
    <StoreId>1</StoreId>
    <Name>My Store</Name>
    <Products>
      <Product>
    <ProductOptions>
      <ProductOption>
        <ProductId>2</ProductId>
        <OptionId>3</OptionId>
        <OrderBy>0</OrderBy>
        <Option>
          <Choices>
        <Choice>
          <OptionChoiceId>8</OptionChoiceId>
          <OptionId>3</OptionId>
          <Name>3'10" x 5'4"</Name>
        </Choice>
        <Choice>
          <OptionChoiceId>9</OptionChoiceId>
          <OptionId>3</OptionId>
          <Name>5'4" x 7'8"</Name>
        </Choice>
        <Choice>
          <OptionChoiceId>10</OptionChoiceId>
          <OptionId>3</OptionId>
          <Name>7'8" x 10'9"</Name>
        </Choice>
          </Choices>
        </Option>
      </ProductOption>
    </ProductOptions>
    <Variants>
      <ProductVariant>
        <Available>true</Available>
        <ProductVariantId>49</ProductVariantId>
        <ProductId>2</ProductId>
        <Option1>8</Option1>
        <Option2>0</Option2>
        <Option3>0</Option3>
        <Option4>0</Option4>
        <Option5>0</Option5>
        <Option6>0</Option6>
        <Option7>0</Option7>
        <Option8>0</Option8>
      </ProductVariant>
      <ProductVariant>
        <Available>true</Available>
        <ProductVariantId>50</ProductVariantId>
        <ProductId>2</ProductId>
        <Option1>9</Option1>
        <Option2>0</Option2>
        <Option3>0</Option3>
        <Option4>0</Option4>
        <Option5>0</Option5>
        <Option6>0</Option6>
        <Option7>0</Option7>
        <Option8>0</Option8>
      </ProductVariant>
      <ProductVariant>
        <Available>true</Available>
        <ProductVariantId>51</ProductVariantId>
        <ProductId>2</ProductId>
        <Option1>10</Option1>
        <Option2>0</Option2>
        <Option3>0</Option3>
        <Option4>0</Option4>
        <Option5>0</Option5>
        <Option6>0</Option6>
        <Option7>0</Option7>
        <Option8>0</Option8>
      </ProductVariant>
    </Variants>
      </Product>
    </Products>
  </Store>
</AbleCommerceExport>

Desired xml output:

<RECORDS>
    <RECORD><!-- For each <ProductVariant> node-->
        <RECORD_ID ID="49" />
         <PROP NAME="ProductVariantId">
            <PVAL>49</PVAL>
        </PROP>
        <PROP NAME="Available">
            <PVAL>true</PVAL>
        </PROP>
        <!-- For each Option[n] retrieve the /Products/Product/ProductOptions/ProductOption/Option/Choices/Choice/Name value -->
        <PROP NAME="Option">
            <PVAL>3'10" x 5'4"</PVAL>
        </PROP>
        <PROP NAME="Option">
            <PVAL>5'4" x 7'8"</PVAL>
        </PROP>
        <PROP NAME="Option">
            <PVAL>7'8" x 10'9"</PVAL>
        </PROP>
    </RECORD>
<RECORDS>

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
    <xsl:output method="xml" indent="yes"/>

  <xsl:template match="Variants">
    <RECORDS>
      <xsl:apply-templates/>
    </RECORDS>
  </xsl:template>

   <xsl:template match="ProductVariant">
    <RECORD>
      <xsl:element name="RECORD_ID">
        <xsl:attribute name="ID">
          <xsl:value-of select="ProductVariantId"/>
        </xsl:attribute>
      </xsl:element>

     <!--??-->

    </RECORD>
  </xsl:template>

  <xsl:template match="text()" /> 

</xsl:stylesheet>

Thanks for any help in advance.

1 Answer 1

1

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="Product">
  <RECORDS>
   <xsl:apply-templates select="Variants/ProductVariant">
    <xsl:with-param name="pOptions" select=
    "ProductOptions/*/Option/*/*"/>
   </xsl:apply-templates>
  </RECORDS>
 </xsl:template>

 <xsl:template match="ProductVariant">
  <xsl:param name="pOptions"/>
   <RECORD>
       <RECORD_ID ID="{ProductVariantId}"/>
       <xsl:apply-templates select="Available|ProductVariantId"/>
       <xsl:apply-templates select=
       "*[starts-with(name(), 'Option') and number(.)]">
         <xsl:with-param name="pOptions" select="$pOptions"/>
       </xsl:apply-templates>
   </RECORD>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'Option')]">
  <xsl:param name="pOptions"/>

   <PROP NAME="Option">
     <PVAL>
       <xsl:value-of select=
       "$pOptions[OptionChoiceId=current()]/Name"/>
     </PVAL>
   </PROP>
 </xsl:template>

 <xsl:template match="Available|ProductVariantId">
   <PROP NAME="{name()}">
     <PVAL><xsl:value-of select="."/></PVAL>
   </PROP>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>

when applied on the provided XML document:

<AbleCommerceExport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Store>
        <StoreId>1</StoreId>
        <Name>My Store</Name>
        <Products>
            <Product>
                <ProductOptions>
                    <ProductOption>
                        <ProductId>2</ProductId>
                        <OptionId>3</OptionId>
                        <OrderBy>0</OrderBy>
                        <Option>
                            <Choices>
                                <Choice>
                                    <OptionChoiceId>8</OptionChoiceId>
                                    <OptionId>3</OptionId>
                                    <Name>3'10" x 5'4"</Name>
                                </Choice>
                                <Choice>
                                    <OptionChoiceId>9</OptionChoiceId>
                                    <OptionId>3</OptionId>
                                    <Name>5'4" x 7'8"</Name>
                                </Choice>
                                <Choice>
                                    <OptionChoiceId>10</OptionChoiceId>
                                    <OptionId>3</OptionId>
                                    <Name>7'8" x 10'9"</Name>
                                </Choice>
                            </Choices>
                        </Option>
                    </ProductOption>
                </ProductOptions>
                <Variants>
                    <ProductVariant>
                        <Available>true</Available>
                        <ProductVariantId>49</ProductVariantId>
                        <ProductId>2</ProductId>
                        <Option1>8</Option1>
                        <Option2>0</Option2>
                        <Option3>0</Option3>
                        <Option4>0</Option4>
                        <Option5>0</Option5>
                        <Option6>0</Option6>
                        <Option7>0</Option7>
                        <Option8>0</Option8>
                    </ProductVariant>
                    <ProductVariant>
                        <Available>true</Available>
                        <ProductVariantId>50</ProductVariantId>
                        <ProductId>2</ProductId>
                        <Option1>9</Option1>
                        <Option2>0</Option2>
                        <Option3>0</Option3>
                        <Option4>0</Option4>
                        <Option5>0</Option5>
                        <Option6>0</Option6>
                        <Option7>0</Option7>
                        <Option8>0</Option8>
                    </ProductVariant>
                    <ProductVariant>
                        <Available>true</Available>
                        <ProductVariantId>51</ProductVariantId>
                        <ProductId>2</ProductId>
                        <Option1>10</Option1>
                        <Option2>0</Option2>
                        <Option3>0</Option3>
                        <Option4>0</Option4>
                        <Option5>0</Option5>
                        <Option6>0</Option6>
                        <Option7>0</Option7>
                        <Option8>0</Option8>
                    </ProductVariant>
                </Variants>
            </Product>
        </Products>
    </Store>
</AbleCommerceExport>

produces the wanted, correct result:

<RECORDS>
   <RECORD>
      <RECORD_ID ID="49"/>
      <PROP NAME="Available">
         <PVAL>true</PVAL>
      </PROP>
      <PROP NAME="ProductVariantId">
         <PVAL>49</PVAL>
      </PROP>
      <PROP NAME="Option">
         <PVAL>3'10" x 5'4"</PVAL>
      </PROP>
   </RECORD>
   <RECORD>
      <RECORD_ID ID="50"/>
      <PROP NAME="Available">
         <PVAL>true</PVAL>
      </PROP>
      <PROP NAME="ProductVariantId">
         <PVAL>50</PVAL>
      </PROP>
      <PROP NAME="Option">
         <PVAL>5'4" x 7'8"</PVAL>
      </PROP>
   </RECORD>
   <RECORD>
      <RECORD_ID ID="51"/>
      <PROP NAME="Available">
         <PVAL>true</PVAL>
      </PROP>
      <PROP NAME="ProductVariantId">
         <PVAL>51</PVAL>
      </PROP>
      <PROP NAME="Option">
         <PVAL>7'8" x 10'9"</PVAL>
      </PROP>
   </RECORD>
</RECORDS>
Sign up to request clarification or add additional context in comments.

3 Comments

Kudos for the correct answer even though the desired xml I provided was incorrect (multiple prop nodes per single record node). Thank you for your help.
@user1223750: I am glad my answer was useful to you. Could you, please, accept the answer (hint: by clicking the check-mark next to the answer)?
Of course. Attempted to vote up but not enough cred. Thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.