How to get row numbers for elements of XML, using

2019-09-14 21:25发布

问题:

Input XML:

  <root>
    <imageLink>
        <url colNumber="1">aa</url>
        <imageTypeCode colNumber="2">PRODUCT_IMAGE</imageTypeCode>
        <languageCode colNumber="3">en</languageCode>
        <languageCode colNumber="3">fr</languageCode>
    </imageLink>
    <imageLink>
        <url colNumber="1">bb</url>
        <imageTypeCode colNumber="2">PRODUCT_IMAGE</imageTypeCode>
        <languageCode colNumber="3">fr</languageCode>
        <commTest>
            <languageCode colNumber="4">fssdr</languageCode>
            <languageCode colNumber="4">fr</languageCode>
            <dummy colNumber="5">DDDUMM</dummy>
        </commTest>
        <commTest>
            <languageCode colNumber="4">fd777r</languageCode>
            <languageCode colNumber="4">fr777</languageCode>
            <dummy colNumber="5">DDD777UMM</dummy>
        </commTest>
        <changedName>
            <languageCode colNumber="4">fd777r</languageCode>
            <languageCode colNumber="4">fr777</languageCode>
            <dummy colNumber="5">DDD777UMM</dummy>
        </changedName>
    </imageLink>
</root>

Expected XML output:

 <?xml version="1.0" encoding="UTF-8"?>
<root>
    <imageLink rowNum="1">
        <url rowNum="1" colNumber="1">aa</url>
        <imageTypeCode rowNum="1" colNumber="2">PRODUCT_IMAGE</imageTypeCode>
        <languageCode rowNum="1" colNumber="3">en</languageCode>
        <languageCode rowNum="2" colNumber="3">fr</languageCode>
    </imageLink>
    <imageLink rowNum="3">
        <url rowNum="3" colNumber="1">bb</url>
        <imageTypeCode rowNum="3" colNumber="2">PRODUCT_IMAGE</imageTypeCode>
        <languageCode rowNum="3" colNumber="3">fr</languageCode>
        <commTest rowNum="3">
            <languageCode rowNum="3" colNumber="4">fssdr</languageCode>
            <languageCode rowNum="4" colNumber="4">fr</languageCode>
            <dummy rowNum="3" colNumber="5">DDDUMM</dummy>
        </commTest>
        <commTest rowNum="5">
            <languageCode rowNum="5" colNumber="4">fd777r</languageCode>
            <languageCode rowNum="6" colNumber="4">fr777</languageCode>
            <dummy rowNum="5" colNumber="5">DDD777UMM</dummy>
        </commTest>
        <changedName rowNum="3">
            <languageCode rowNum="3" colNumber="4">fd777r</languageCode>
            <languageCode rowNum="4" colNumber="4">fr777</languageCode>
            <dummy rowNum="3" colNumber="5">DDD777UMM</dummy>
        </changedName>
    </imageLink>
</root>

this process happens in multiple levels of element complexity, these row numbers are assigned so that it enters into an excel sheet in the form of rows and columns

can anyone please assist me?

回答1:

I am not sure why the edit removed the XSLT 2.0 tag but as a follow-up to the earlier problem with two levels of nesting I post this XSLT 2.0 stylesheet that should work with three levels of nesting:

<?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:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates select="*[1]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="root//*[*]">
        <xsl:param name="row" select="1"/>
        <xsl:variable name="copy" as="element()">
            <xsl:copy>
                <xsl:attribute name="rowNum" select="$row"/>
                <xsl:apply-templates select="*[1]">
                    <xsl:with-param name="row" select="$row"/>
                </xsl:apply-templates>
            </xsl:copy>
        </xsl:variable>
        <xsl:copy-of select="$copy"/>
        <xsl:apply-templates select="following-sibling::*[1]">
            <xsl:with-param name="row" select="max($copy/descendant-or-self::*[@rowNum]/@rowNum) + 1"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="root/*//*[not(*)]">
        <xsl:param name="row"/>
        <xsl:variable name="index" as="xs:integer">
            <xsl:number/>
        </xsl:variable>
        <xsl:variable name="copy" as="element()">
            <xsl:copy>
                <xsl:attribute name="rowNum" select="$row - 1 + $index"/>
                <xsl:copy-of select="@*, node()"/>
            </xsl:copy>         
        </xsl:variable>
        <xsl:copy-of select="$copy"/>
        <xsl:apply-templates select="following-sibling::*[1]">
            <xsl:with-param name="row" select="$row"/>
        </xsl:apply-templates>
    </xsl:template>

</xsl:stylesheet>