0
    <MemoPad>
       <ENTRYTYPE>ReviewFees</ENTRYTYPE>
       <ENTRYDATETIME>2017-09-05</ENTRYDATETIME>
       <USERID>admin</USERID>
      <MEMOENTRY>Review fees test</MEMOENTRY>
    </MemoPad>
    <MemoPad>
       <ENTRYTYPE>UnderwriterReview</ENTRYTYPE>
        <ENTRYDATETIME>2017-04-12</ENTRYDATETIME>
         <USERID>ADMIN</USERID>
         <MEMOENTRY>Underwriter Rule</MEMOENTRY>
    </MemoPad>
     <MemoPad>
          <ENTRYTYPE>UnderwriterReview</ENTRYTYPE>
          <ENTRYDATETIME>2017-09-05</ENTRYDATETIME>
          <USERID>admin</USERID>
          <MEMOENTRY>month bank statement. </MEMOENTRY>
     </MemoPad>

I tried a lot writting XSLT for above portion but couldnt crack it down. What I am looking for is basically I want to iterate over each memopad item and in memopad for each EntryType I would like to create an xml like

      <ReviewFeesType>
           <ReviewFee>               
                <ENTRYDATETIME>2017-09-05</ENTRYDATETIME>
                <USERID>admin</USERID>
                <MEMOENTRY>Review fees test</MEMOENTRY>
           </ReviewFee>
       </ReviewFeesType>

but now for entry types which are multiple type should be created as below.

     <UnderwriterReviewType>
        <UnderwriterReview>
            <ENTRYDATETIME>2017-04-12</ENTRYDATETIME>
            <USERID>ADMIN</USERID>
            <MEMOENTRY>Underwriter Rule</MEMOENTRY>
        </UnderwriterReview>
         <UnderwriterReview>
             <ENTRYDATETIME>2017-09-05</ENTRYDATETIME>
             <USERID>admin</USERID>
             <MEMOENTRY>month bank statement. </MEMOENTRY>
           </UnderwriterReview>
     </UnderwriterReviewType>  

How can i write an XSLT for this? Please help.

What I have tried is

   <MemoPads>
      <xsl:for-each select="MemoPad">            
        <xsl:element name="{ENTRYTYPE}">
          <ENTRYDATETIME>
            <xsl:value-of select="ENTRYDATETIME"/>
          </ENTRYDATETIME>
          <USERID>
            <xsl:value-of select="USERID"/>
          </USERID>
          <MEMOENTRY>
            <xsl:value-of select="MEMOENTRY"/>
          </MEMOENTRY>
        </xsl:element>            
      </xsl:for-each>
    </MemoPads>

Thank you in advance.

7
  • I am novice to XSLT Commented Sep 15, 2017 at 14:59
  • What have you tried so far? Where is your XSLT that you did? Commented Sep 15, 2017 at 15:04
  • Hello Anton, I have updated my question to give you a bit more idea Commented Sep 15, 2017 at 15:18
  • 2
    It is tricky in general to answer questions about fragmentary code and / or data, and it is especially tricky for XSLT and other XML technologies relying on XPath. Present a minimal reproducible example demonstrating the problem. If you are uncertain what an MCVE is, then do follow the link to find out what we expect in that regard. Commented Sep 15, 2017 at 15:49
  • So you want to group the MemoPad elements by ENTRYTYPE, see w3.org/TR/xslt-30/#grouping-examples Commented Sep 15, 2017 at 15:50

1 Answer 1

1

This is a grouping example. If you are using XSLT 1.0, a <xsl:key> needs to be declared.

<xsl:key name="kEntryType" match="MemoPad" use="ENTRYTYPE" />

The input XML provided is not well-formed as it does not contain root node, hence I have assumed that <MemoPads> is the root node. The below XSLT will help in getting the desired output. The comments should help understand the logic.

XSLT 1.0

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

    <!-- declare a grouping key -->
    <xsl:key name="kEntryType" match="MemoPad" use="ENTRYTYPE" />

    <xsl:template match="/">
        <!-- create root node in output -->
        <MemoPads>
            <!-- loop for all the groups based on the declared key -->
            <xsl:for-each select="//MemoPad[generate-id() = generate-id(key('kEntryType', ENTRYTYPE)[1])]">
                <!-- create parent element for the grouped elements -->
                <xsl:element name="{concat(ENTRYTYPE,'Type')}">
                    <!-- loop through the set of elements within the key -->
                    <xsl:for-each select="key('kEntryType', ENTRYTYPE)">
                        <!-- create element as required in the output -->
                        <xsl:element name="{ENTRYTYPE}">
                            <!-- copy all elements except the ENTRYTYPE -->
                            <xsl:copy-of select="*[not(self::ENTRYTYPE)]" />
                        </xsl:element>
                    </xsl:for-each>
                </xsl:element>
            </xsl:for-each>
        </MemoPads>
    </xsl:template>
</xsl:stylesheet>

Output

<MemoPads>
    <ReviewFeesType>
        <ReviewFees>
            <ENTRYDATETIME>2017-09-05</ENTRYDATETIME>
            <USERID>admin</USERID>
            <MEMOENTRY>Review fees test</MEMOENTRY>
        </ReviewFees>
    </ReviewFeesType>
    <UnderwriterReviewType>
        <UnderwriterReview>
            <ENTRYDATETIME>2017-04-12</ENTRYDATETIME>
            <USERID>ADMIN</USERID>
            <MEMOENTRY>Underwriter Rule</MEMOENTRY>
        </UnderwriterReview>
        <UnderwriterReview>
            <ENTRYDATETIME>2017-09-05</ENTRYDATETIME>
            <USERID>admin</USERID>
            <MEMOENTRY>month bank statement. </MEMOENTRY>
        </UnderwriterReview>
    </UnderwriterReviewType>
</MemoPads>
Sign up to request clarification or add additional context in comments.

2 Comments

Hello Aniket..This is genius..It worked perfectly. However I am wondering about XSD now. Do we write xsd for such tricky XSLT's?
I am not very sure about XSDs since the output XML contains certain elements that are dynamically created. You may want to put it up as a different question for experts to answer.

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.