0

I am trying to create an XSLT that will convert an array into unique sequential elements. I am probably not explaining this correctly so I will show you:

Current XML

<?xml version="1.0" encoding="UTF-8"?>
<DocumentRequests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <PlanID>20151014_103605</PlanID>
            <LetterType>
                        <Fund>Yes</Fund>
                        <Adding>Yes</Adding>
                        <Bau>Yes</Bau>
            </LetterType>
            <PlanNumbers>
                        <PlanNumber>A01</PlanNumber>
                        <PlanNumber>A02</PlanNumber>
                        <PlanNumber>A03</PlanNumber>
                        <PlanNumber>A04</PlanNumber>
                        <PlanNumber>A05</PlanNumber>
                        <PlanNumber>A06</PlanNumber>
                        <PlanNumber>456</PlanNumber>
            </PlanNumbers>
</DocumentRequests>

Current XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" 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">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
     <xsl:template match="*">
            <SourceFeedbackTransformed>            
                <PlanAdminID><xsl:value-of select="PlanAdminID" /></PlanAdminID>    
                <xsl:for-each select="LetterType">
                     <xsl:copy-of select="*" copy-namespaces="no"/>
                </xsl:for-each>
                <xsl:for-each select="PlanNumbers">
                      <xsl:copy-of select="*" copy-namespaces="no"/>
                </xsl:for-each>
            </SourceFeedbackTransformed>           
    </xsl:template>
</xsl:stylesheet>

Current output

<?xml version="1.0" encoding="UTF-8"?>
<SourceFeedbackTransformed xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
            <PlanAdminID/>
            <Fund>Yes</Fund>
            <Adding>Yes</Adding>
            <Bau>Yes</Bau>
            <PlanNumber>A01</PlanNumber>
            <PlanNumber>A02</PlanNumber>
            <PlanNumber>A03</PlanNumber>
            <PlanNumber>A04</PlanNumber>
            <PlanNumber>A05</PlanNumber>
            <PlanNumber>A06</PlanNumber>
            <PlanNumber>456</PlanNumber>
</SourceFeedbackTransformed>**

Desired Output

<?xml version="1.0" encoding="UTF-8"?>
<SourceFeedbackTransformed xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
            <PlanAdminID/>
            <Fund>Yes</Fund>
            <Adding>Yes</Adding>
            <Bau>Yes</Bau>
            <PlanNumber1>A01</PlanNumber1>
            <PlanNumber2>A02</PlanNumber2>
            <PlanNumber3>A03</PlanNumber3>
            <PlanNumber4>A04</PlanNumber4>
            <PlanNumber5>A05</PlanNumber5>
            <PlanNumber6>A06</PlanNumber6>
            <PlanNumber7>456</PlanNumber7>
</SourceFeedbackTransformed>

As you can see the Array with 7 values has been converted to 7 different elements.

Thank you for your help.

Cheers,

4
  • "Has been" or "must be"? There is nothing to change the tags in your code, so xsl:copy does what it's told to do. Commented Oct 16, 2015 at 20:21
  • I understand it is doing as it is told. I want to know how to tell it to do what I want :). Which is the desired output. Each <PlanNumber> becomes <PlanNumberX> 'x' being unique to for each value. Commented Oct 16, 2015 at 20:24
  • Are you sure you want to do this? Having numbered elements may make it more difficult to process the result. Commented Oct 16, 2015 at 20:34
  • Yes, I am sure. But I do completely understand your point. Basically it is due to not having any other options and resources. We need to create a Database which will have new files added to it weekly. Some in the form like the one discussed in this thread and and another file (different data points, different XML Layout and tens of thousands of individual records) using the <PlanAdminID> to 'connect' them. Due to lack of resources/options we are doing this in MS Access. We will need to be able to run queries that will use data across both files to generate a report. This will be a stop gap Commented Oct 19, 2015 at 14:51

1 Answer 1

1

You can get the result you're after quite easily by:

XSLT 2.0

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

<xsl:template match="/DocumentRequests">
    <SourceFeedbackTransformed>            
        <PlanAdminID><xsl:value-of select="PlanID" /></PlanAdminID>    
        <xsl:copy-of select="LetterType/*" copy-namespaces="no"/>
        <xsl:for-each select="PlanNumbers/PlanNumber">
            <xsl:element name="PlanNumber{position()}">
                <xsl:value-of select="."/>
            </xsl:element>
        </xsl:for-each>
    </SourceFeedbackTransformed>           
</xsl:template>

</xsl:stylesheet>

Note:
I have changed your:

<xsl:value-of select="PlanAdminID" />

to:

<xsl:value-of select="PlanID" />

as there is no PlanAdminID element in your input. If you really want to output an empty <PlanAdminID/> element as shown in your requested output, then you could do so directly, without fetching the value of a non-existing node.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Michael. I just learned what xslt today and spent hours on this.

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.