paras as list and sub list format

2019-08-21 07:41发布

I want para's as list format sublist also is in para format as list format

My Input XML File:

<?xml version="1.0" encoding="UTF-8"?>


<chapter>
<title>Base Food</title>
<subsection>
<title>Nothing</title>
<body>
<p>  (a)<tab/>1Y The Act also states that the may undertake a review of the definition of the term.</p>
<p>  (b)<tab/>The Act also states that the may undertake a review of the definition of the term:</p>
<p>  (i)<tab/>Act also states that the may undertake a review of the definition of the term.</p>
<p>  (ii)<tab/>States that the may undertake a review of the definition of the term.</p>
</body>
</subsection>
</chapter>

My XSLT Coding is

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes" omit-xml-declaration="no"></xsl:output>

<xsl:template match="/">
<xsl:apply-templates></xsl:apply-templates>
</xsl:template>


<xsl:template match="chapter">
<chapter>
<xsl:apply-templates/>
</chapter>
</xsl:template>

<xsl:template match="subsection">
<section>
<xsl:apply-templates/>
</section>
</xsl:template>

<xsl:template match="p">
<para>
 <xsl:apply-templates/>
</para>
</xsl:template>

<xsl:template match="title">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>

</xsl:stylesheet>


</xsl:stylesheet>

I am getting output as

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<chapter>
<title>Base Food</title>
<section>
<title>Nothing</title>
<para>  (a)<tab/>1Y The Act also states that the may undertake a review of the definition of the term.</para>
<para>  (b)<tab/>The Act also states that the may undertake a review of the definition of the term:</para>
<para>  (i)<tab/>Act also states that the may undertake a review of the definition of the term.</para>
<para>  (ii)<tab/>States that the may undertake a review of the definition of the term.</para>
</section>
</chapter>

but i want output tab tag before text as item attribute

output needed as

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<chapter>
<title>Base Food</title>
<section level="sect1" num="I" number-type="manual">
<title>Nothing</title>
<orderedlist type="manual">
<item num="(a)"><para>1Y The Act also states that the may undertake a review of the definition of the term.</para></item>
<item num="(b)"><para>The Act also states that the may undertake a review of the definition of the term:</para>
<orderedlist type="manual">
<item num="(i)"><para>Act also states that the may undertake a review of the definition of the term.</para></item>
<item num="(ii)"><para>States that the may undertake a review of the definition of the term.</para></item></orderedlist></item></orderedlist>
</section>
</chapter>

Please assist me.

Thanks in Advance

标签: xml xslt
1条回答
女痞
2楼-- · 2019-08-21 08:08

Here is an attempt to write a template matching body to use for-each-group group-adjacent to identify adjacent p elements first and then to use a recursive function to find nested list using for-each-group group-starting-with:

<?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"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs math mf" version="3.0">

    <xsl:param name="patterns" as="xs:string*" select="'^\s*(\(a\))', '^\s*(\(i\))'"/>

    <xsl:output indent="yes"/>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:function name="mf:list-group" as="node()*">
        <xsl:param name="input" as="element()*"/>
        <xsl:sequence select="mf:list-group($input, $patterns)"/>
    </xsl:function>

    <xsl:function name="mf:list-group" as="node()*">
        <xsl:param name="input" as="node()*"/>
        <xsl:param name="patterns" as="xs:string*"/>
        <xsl:choose>
            <xsl:when test="$patterns[1]">
                <xsl:for-each-group select="$input"
                    group-starting-with="p[matches(., $patterns[1])]">
                    <xsl:choose>
                        <xsl:when test="self::p[matches(., $patterns[1])]">
                            <orderedlist type="manual">
                                <xsl:sequence select="mf:list-group(current-group(), $patterns[position() gt 1])"></xsl:sequence>
                            </orderedlist>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="current-group()"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="$input"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>

    <xsl:template match="body">
        <xsl:for-each-group select="*"
            group-adjacent="boolean(self::p[node()[1][self::text()[matches(., '^\s*\([a-z]+\)$')]] and node()[2][self::tab]])">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <xsl:sequence select="mf:list-group(current-group())"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="p">
        <item num="{replace(node()[1], '^\s+', '')}">
            <para><xsl:apply-templates select="node()[position() gt 2]"/></para>
        </item>
    </xsl:template>
</xsl:stylesheet>

I have written that as XSLT 3.0 as supported by Saxon 9.8 but you should be able to incorporate all but the <xsl:mode on-no-match="shallow-copy"/> into your XSLT 2.0 stylesheet with your other templates doing the transformation you already have.

查看更多
登录 后发表回答