Amrendra Kumar
Amrendra Kumar

Reputation: 1816

Creating element with attribute

I want to create an element by matching @pagebreak. @pagebreak is appearing with multiple parent like para, table, etc...

INPUT XML:

<?xml version="1.0" encoding="UTF-8"?>
    <root>
        <child1>
            <para>This is first para.</para>
            <para pagebreak="yes">This is second para.</para>
            <para>This is first para.</para>
            <table>
                <tr>
                    <td>first table</td>
                </tr>
            </table>
        </child1>
        <child1>
            <para>This is first para.</para>
            <para>This is second para.</para>
            <para>This is first para.</para>
            <table pagebreak="yes">
                <tr>
                    <td>second table</td>
                </tr>
            </table>
        </child1>
    </root>

CURRENT OUTPUT:

<?xml version="1.0" encoding="UTF-8"?>
<article>
    <section>
        <p class="p_1">This is first para.</p>
        <div>
            <pagebreak type="yes"/>
        </div>
        <para>This is second para.</para>
        <p class="p_3">This is first para.</p>
        <table id="tab_1">
            <tr>
                <td>first table</td>
            </tr>
        </table>
    </section>
    <section>
        <p class="p_1">This is first para.</p>
        <p class="p_2">This is second para.</p>
        <p class="p_3">This is first para.</p>
        <div>
            <pagebreak type="yes"/>
        </div>
        <table>
            <tr>
                <td>second table</td>
            </tr>
        </table>
    </section>
</article>

DESIRED OUTPUT:

<?xml version="1.0" encoding="UTF-8"?>
<article>
    <section>
        <p class="p_1">This is first para.</p>
        <div>
            <pagebreak type="yes"/>
        </div>
        <p class="p_2">This is second para.</p>
        <p class="p_3">This is first para.</p>
        <table id="tab_1">
            <tr>
                <td>first table</td>
            </tr>
        </table>
    </section>
    <section>
        <p class="p_1">This is first para.</p>
        <p class="p_2">This is second para.</p>
        <p class="p_3">This is first para.</p>
        <div>
            <pagebreak type="yes"/>
        </div>
        <table id="tab_2">
            <tr>
                <td>second table</td>
            </tr>
        </table>
    </section>
</article>

template for element/@pagebrake should be applied same as without @pagebrake.

NOTE: In output you can see that:

XSLT I've USED:

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

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

    <xsl:template match="para">
        <p class="{concat('p_', count(preceding-sibling::para)+1)}">
            <xsl:apply-templates select="@* | node()"/>
        </p>
    </xsl:template>

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

    <xsl:template match="table">
        <xsl:variable name="num"><xsl:number/></xsl:variable>
        <table id="{concat('tab_', $num)}">
            <xsl:apply-templates select="@* | node()"/>
        </table>
    </xsl:template>


    <xsl:template match="*[@pagebreak]">
        <div><pagebreak type="yes"/></div>
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>


</xsl:stylesheet>

Upvotes: 0

Views: 29

Answers (1)

Tim C
Tim C

Reputation: 70648

The problem is in your template matching *[@pagebreak]. Instead of doing xsl:apply-templates, you should do xsl:next-match so that the current node is continued to be matched, rather than going on to its child.

<xsl:template match="*[@pagebreak]">
    <div><pagebreak type="yes"/></div>
    <xsl:next-match />
</xsl:template>

You would also need to add a template to stop @pagebreak being output too.

<xsl:template match="@pagebreak" />

Upvotes: 1

Related Questions