0
votes

I have a xml like follows,

<doc>
    <section>
        <p id="main">main 1</p>
        <p id="main">main 2</p>
        <p id="para1">para1 1</p>
        <p id="main">
            <p>para1 sub1</p>
            <p>para1 sub2</p>
        </p>
        <p id="main">para1 main2</p>
        <p id="main">para1 main3</p>
        <p id="chapter1">
            <p>para2 sub1</p>
            <p>para2 sub2</p>
          </p>
        <p id="main">para2 main1</p>
        <p id="main">para2 main2</p>
        <p id="main">para2 main3</p>
        <p id="para1">para1 1</p>
        <p id="main">
            <p>para 1 sub3</p>
            <p> para1 sub4</p>
          </p>
        <p id="main">para1 main2</p>
    </section>
</doc>

As you can see XML has only one <section> and <p> nodes. and <p> nodes has different attributes 'main', 'para1' and 'para2' what I need is by analyzing <p> nodes separates to <p> nodes to <section> where it starts new attribute of <p>. and change 'para1' and 'para2' attributes to 'main-para1' and 'main-para2' So my expected output is,

<doc>
    <section>
        <p id="main">main 1</p>
        <p id="main">main 2</p>
    </section>
    <section>
        <p id="main-para1">para1 1</p>
        <p id="main">
            <p>para1 sub1</p>
            <p>para1 sub2</p>
        </p>
        <p id="main">para1 main2</p>
        <p id="main">para1 main3</p>
    </section>
    <section>
        <p id="main-chapter1">
            <p>para2 sub1</p>
            <p>para2 sub2</p>
        </p>
        <p id="main">para2 main1</p>
        <p id="main">para2 main2</p>
        <p id="main">para2 main3</p>
     </section>
    <section>
        <p id="main-para1">para1 1</p>
        <p id="main">
            <p>para 1 sub3</p>
            <p>para 1 sub4</p>
        </p>
        <p id="main">para1 main2</p>
    </section>
</doc>

the xsl that I've written to do my task is follows

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

<xsl:template match="p[preceding-sibling::p[@id='para1']][following-sibling::p[@id='para2']]"/>
<xsl:template match="p[preceding-sibling::p[@id='para2']][following-sibling::p[@id='para1']]"/>

<xsl:template match="p[@id='para1']">
    <section>
        <p id="main-para1">
            <xsl:apply-templates/>
        </p>
    </section>
</xsl:template>

<xsl:template match="p[@id='para2']">
    <section>
        <p id="main-para2">
            <xsl:apply-templates/>
        </p>
    </section>
</xsl:template>

However I've several problems that I'm unable to solve in above XSL code,

1) new <section> is added as chid to existing <section> node. but I need it as following-sibling to existing <section> (as shown in expected output.)

2) the following-siblings of <p id="main-para1"> and <p id="main-para1"> are not copied in to <section>

can anyone suggest how can I modified my code to get the expected output?

Thanks in advanced !

1
This is impossible to follow. Please put some identifying content into your paras (e.g. <p id="main">a</p>, <p id="main">b</p>, etc.) so that we can tell how the result relates to the source.michael.hor257k
@michael.hor257k , Thanks for the comment. Edited the question and added some content.sanjay
I believe you have a mistake here: <p id="para 1 main1">. Or I really don't understand it.michael.hor257k
@michael.hor257k , Yes, when I added the contented I've made that mistake. I've corrected it and and updated the questionsanjay

1 Answers

2
votes

I believe this returns the expected result:

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"/>

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

<xsl:template match="section">
    <xsl:for-each-group select="p" group-starting-with="p[starts-with(@id, 'para')]">
        <section>
            <xsl:apply-templates select="current-group()"/>
        </section>      
    </xsl:for-each-group>
</xsl:template>

<xsl:template match="p/@id[starts-with(., 'para')]">
    <xsl:attribute name="id" select="concat('main-', .)"/>
</xsl:template>

</xsl:stylesheet>