Tricky XML Input - Require XSLT 2.0 Solution

We have this Input XML:

<Notes>
  <Note>
        <ConciseNote>(A)
		<Topic TopicName="Education Matter">
            <TopicProvision P="S.1"></TopicProvision>
			<TopicProvision P="S.2"></TopicProvision>
          </Topic>
		  <Topic TopicName="Service Matter">
            <TopicProvision P="S.1"></TopicProvision>
          </Topic>
		  This is the second portion of concise text of the topic<bL></bL>
          <Topic TopicName ="Matrimonial Matter">
            <TopicProvision P="S.3"></TopicProvision>
            <TopicProvision P="S.4"></TopicProvision>
          </Topic>
          <Topic TopicName ="Defence Matter">
            <TopicProvision P="S.5"></TopicProvision>
            <TopicProvision P="S.6"></TopicProvision>
          </Topic>
        </ConciseNote>
        <DetailedNote>
          <DetailedNoteParagraphText>This is the 1st Paragraph of Detailed Note</DetailedNoteParagraphText>
          <DetailedNoteParagraphText>This is the 2nd Paragraph of Detailed Note</DetailedNoteParagraphText>
          <PageReference>pagereference-1</PageReference>
          <DetailedNoteParagraphText>This is the 3rd Paragraph of Detailed Note
<DetailedNoteParagraphNumber>(Para<Link L="TEXT_TO_LINK">10</Link>)</DetailedNoteParagraphNumber>
          </DetailedNoteParagraphText>
        </DetailedNote>
   </Note>
</Notes>

Open in new window


We require the following Output XML:

<field Name="HeadConciseNote">
   <span class="ConciseNote">
		<p>(A) Education Matter s.1, s.2;Service Matter s.1 This is the second portion of concise text of the topic</p>
		<p> Matrimonial Matter s.3, s.4,  Defence Matter s.5, s.6 </p>
   </span>   
   <span class="DetailedNote">
		<p>This is the 1st Paragraph of Detailed Note</p>
		<p>This is the 2nd Paragraph of Detailed Note</p>
		<p>pagereference-1</p>
		<p>This is the 3rd Paragraph of Detailed Note</p>
		<p>(Para<Link L="TEXT_TO_LINK">10</Link>)</DetailedNoteParagraphNumber></p></span>
 </field>

Open in new window


The two instances of text - i.e. (A) and the Concise Text appearing between the TopicName tag is quite tricky to resolve.

Could anyone help us out with XSLT 2.0 Code for generating the xml output?

Any help is appreciated. Thanks in advance.
Adwait ChitaleyAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Gertone (Geert Bormans)Information ArchitectCommented:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output indent="yes"></xsl:output>
    
    <xsl:template match="Notes">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="Notes/Note">
        <field Name="HeadConciseNote">
            <xsl:apply-templates></xsl:apply-templates>
        </field>
   </xsl:template>
    
    <xsl:template match="ConciseNote">
        <span class="ConciseNote">
            <xsl:for-each-group select="node()" group-starting-with="bL">
                <p>
                    <xsl:apply-templates select="current-group()/self::node()"/>
                </p>
            </xsl:for-each-group>
        </span>
    </xsl:template>
    
    <xsl:template match="Topic">
        <xsl:if test="preceding-sibling::Topic">
            <xsl:text>;</xsl:text>
        </xsl:if>
        <xsl:text> </xsl:text>
        <xsl:value-of select="@TopicName"/>
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="TopicProvision"/>
    </xsl:template>
    
    <xsl:template match="TopicProvision">
        <xsl:if test="preceding-sibling::TopicProvision">
            <xsl:text>, </xsl:text>
        </xsl:if>
        <xsl:value-of select="@P"></xsl:value-of>
        
    </xsl:template>
    
    <xsl:template match="ConciseNote/text()">
        <xsl:value-of select="normalize-space(.)"/>
    </xsl:template>
    
</xsl:stylesheet>

Open in new window

Gertone (Geert Bormans)Information ArchitectCommented:
That is not production proof of course,
but it will get you started (what you named the hard part is taken care of)
Gertone (Geert Bormans)Information ArchitectCommented:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output indent="yes"></xsl:output>
    
    <xsl:template match="Notes">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="Notes/Note">
        <field Name="HeadConciseNote">
            <xsl:apply-templates></xsl:apply-templates>
        </field>
   </xsl:template>
    
    <xsl:template match="ConciseNote">
        <span class="ConciseNote">
            <xsl:for-each-group select="node()" group-starting-with="bL">
                <p>
                   <xsl:variable name="cur-p">
                       <xsl:apply-templates select="current-group()/self::node()"/>
                   </xsl:variable>
                   <xsl:value-of select="replace(normalize-space($cur-p), '^(.+?);?$', '$1')"/> 
                </p>
            </xsl:for-each-group>
        </span>
    </xsl:template>
    
    <xsl:template match="Topic">
         <xsl:text> </xsl:text>
        <xsl:value-of select="@TopicName"/>
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="TopicProvision"/>
        <xsl:text>; </xsl:text>
    </xsl:template>
    
    <xsl:template match="TopicProvision">
        <xsl:if test="preceding-sibling::TopicProvision">
            <xsl:text>, </xsl:text>
        </xsl:if>
        <xsl:value-of select="@P"></xsl:value-of>
     </xsl:template>
    
    <xsl:template match="DetailedNote">
        <span class="DetailedNote">
            <xsl:apply-templates></xsl:apply-templates>
        </span>
    </xsl:template>

    <xsl:template match="DetailedNoteParagraphText | PageReference">
        <p>
            <xsl:apply-templates></xsl:apply-templates>
        </p>
        <xsl:apply-templates select="DetailedNoteParagraphNumber" mode="ext"/>
    </xsl:template>
    
    <xsl:template match="DetailedNoteParagraphNumber"/>

    <xsl:template match="DetailedNoteParagraphNumber" mode="ext">
        <p>
            <xsl:apply-templates></xsl:apply-templates>
        </p>
    </xsl:template>
    
    <xsl:template match="Link">
        <Link>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </Link>
    </xsl:template>
    
    
    
</xsl:stylesheet>

Open in new window

Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

Gertone (Geert Bormans)Information ArchitectCommented:
That one is pretty bullet proof now, I hope you can fine tune it to your needs
Adwait ChitaleyAuthor Commented:
Geert Bormans,

Thanks for your input. Let me check and revert.
Adwait ChitaleyAuthor Commented:
Geert,

Thank you for your input. Saved us quite some time. Works great for us. We've carried out the rest of the work.

Small hitch though ... the XSLT groups the matter using <bl> tag which may not always appear in the data. Can you please help us with the modified version if the following is to be obtained : (Data represented without <BL> Tag)

Input XML:

<Notes>
  <Note>
        <ConciseNote>(A)
		<Topic TopicName="Education Matter">
            <TopicProvision P="S.1"></TopicProvision>
			<TopicProvision P="S.2"></TopicProvision>
          </Topic>
		  <Topic TopicName="Service Matter">
            <TopicProvision P="S.1"></TopicProvision>
          </Topic>
		  This is the second portion of concise text of the topic
          <Topic TopicName ="Matrimonial Matter">
            <TopicProvision P="S.3"></TopicProvision>
            <TopicProvision P="S.4"></TopicProvision>
          </Topic>
          <Topic TopicName ="Defence Matter">
            <TopicProvision P="S.5"></TopicProvision>
            <TopicProvision P="S.6"></TopicProvision>
          </Topic>
        </ConciseNote>
        <DetailedNote>
          <DetailedNoteParagraphText>This is the 1st Paragraph of Detailed Note</DetailedNoteParagraphText>
          <DetailedNoteParagraphText>This is the 2nd Paragraph of Detailed Note</DetailedNoteParagraphText>
          <PageReference>pagereference-1</PageReference>
          <DetailedNoteParagraphText>This is the 3rd Paragraph of Detailed Note
<DetailedNoteParagraphNumber>(Para<Link L="TEXT_TO_LINK">10</Link>)</DetailedNoteParagraphNumber>
          </DetailedNoteParagraphText>
        </DetailedNote>
   </Note>
</Notes>

Open in new window


Output desired:


<field Name="HeadConciseNote">
   <span class="ConciseNote">
		<p>(A) Education Matter s.1, s.2;Service Matter s.1 This is the second portion of concise text of the topic</p>
		<p> Matrimonial Matter s.3, s.4,  Defence Matter s.5, s.6 </p>
   </span>   
   <span class="DetailedNote">
		<p>This is the 1st Paragraph of Detailed Note</p>
		<p>This is the 2nd Paragraph of Detailed Note</p>
		<p>pagereference-1</p>
		<p>This is the 3rd Paragraph of Detailed Note</p>
		<p>(Para<Link L="TEXT_TO_LINK">10</Link>)</DetailedNoteParagraphNumber></p></span>
 </field>

Open in new window

Gertone (Geert Bormans)Information ArchitectCommented:
well, I need some hint on what the logic is for seperating the <P> constructs
You don't tell me why exactly the third topic is a group seperator
I can only implement on clear specs of course
So... what is exactly the trigger for seperating the topics into seperate P
Adwait ChitaleyAuthor Commented:
Geert,

We have attached a word document containing details to this issue. Request you to please review.

Thanks.

Concise-Note-Tag-can-be-divided-into-fou
Gertone (Geert Bormans)Information ArchitectCommented:
Cool, very clear specs, thank you.
I hope you understand it was hard to figure that out on my own :-)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output indent="yes"></xsl:output>
    
    <xsl:template match="Notes">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="Notes/Note">
        <field Name="HeadConciseNote">
            <xsl:apply-templates></xsl:apply-templates>
        </field>
    </xsl:template>
    
    <xsl:template match="ConciseNote">
        <span class="ConciseNote">
            <xsl:for-each-group select="node()" group-ending-with="text()[normalize-space()][preceding-sibling::node()[1]/self::Topic]">
                <p>
                    <xsl:variable name="cur-p">
                        <xsl:apply-templates select="current-group()/self::node()"/>
                    </xsl:variable>
                    <xsl:value-of select="replace(normalize-space($cur-p), '^(.+?);?$', '$1')"/> 
                </p>
            </xsl:for-each-group>
        </span>
    </xsl:template>
    
    <xsl:template match="Topic">
        <xsl:text> </xsl:text>
        <xsl:value-of select="@TopicName"/>
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="TopicProvision"/>
        <xsl:text>; </xsl:text>
    </xsl:template>
    
    <xsl:template match="TopicProvision">
        <xsl:if test="preceding-sibling::TopicProvision">
            <xsl:text>, </xsl:text>
        </xsl:if>
        <xsl:value-of select="@P"></xsl:value-of>
    </xsl:template>
    
    <xsl:template match="DetailedNote">
        <span class="DetailedNote">
            <xsl:apply-templates></xsl:apply-templates>
        </span>
    </xsl:template>
    
    <xsl:template match="DetailedNoteParagraphText | PageReference">
        <p>
            <xsl:apply-templates></xsl:apply-templates>
        </p>
        <xsl:apply-templates select="DetailedNoteParagraphNumber" mode="ext"/>
    </xsl:template>
    
    <xsl:template match="DetailedNoteParagraphNumber"/>
    
    <xsl:template match="DetailedNoteParagraphNumber" mode="ext">
        <p>
            <xsl:apply-templates></xsl:apply-templates>
        </p>
    </xsl:template>
    
    <xsl:template match="Link">
        <Link>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </Link>
    </xsl:template>
    
    
    
</xsl:stylesheet>

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Adwait ChitaleyAuthor Commented:
Geert,

Many thanks for a wonderful and a timely solution. I hope you'll send your mailing address on achitaley@gmail.com and give us a chance to extend our thanks.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
XML

From novice to tech pro — start learning today.