Complex autonumbers in XSL

2019-09-16 05:59发布

问题:

I'm wondering how can I create different autonumbering series in XSL. I understand that the structure into which I need to transform my file is rather complicated and unnecessarily byzantine. However, I think it really is what I need... I got it to work quite far with simple position()'s, but I just don't find information online about similar cases that could take me onward. So here it goes:

XML is like this:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="test.xsl" type="text/xsl"?>
<XML>
<thing>line</thing>
<thing>line</thing>
<thing>line</thing>
<thing>line</thing>
</XML>

And I need a structure which is like this:

<XML>
<ids>
<id id="1" nr="0"/>
<id id="2" nr="10"/>
<id id="3" nr="20"/>
<id id="4" nr="30"/>
<id id="5" nr="40"/>
<id id="6" nr="50"/>
<id id="7" nr="60"/>
<id id="8" nr="70"/>
</ids>
<info_things>
<thing thing_id="1" id1="1" id2="2"></thing>
<thing thing_id="2" id1="3" id2="4"></thing>
<thing thing_id="3" id1="5" id2="6"></thing>
<thing thing_id="4" id1="7" id2="8"></thing>
</info_things>
<things>
<thing thing_id="5" ref_id="1">line</thing>
<thing thing_id="6" ref_id="2">line</thing>
<thing thing_id="7" ref_id="3">line</thing>
<thing thing_id="8" ref_id="4">line</thing>
</things>
</XML>

This breaks down into several sub-questions that are still not solved:

  1. So I need to generate twice the number of id's than I have the original nodes.
  2. For id nr's I would like to generate a list that starts from 0 and increases by 10, but it can also start from 10 as I have it now, that's acceptable.
  3. Thing id's have to be unique, so they have to continue in from where they were left in ...

I have now this:

<?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 method="xml" omit-xml-declaration="no" />
<xsl:template match="/">
 <XML>
    <ids>
       <xsl:for-each select="//thing">
           <id id="{position()}" nr="{position()*10}"/>
       </xsl:for-each>
    </ids>
    <info_things>
        <xsl:for-each select="//thing">
            <thing thing_id="{position()}" id1="{position()*2-1}" id2="{position()*2}"></thing>
        </xsl:for-each>
    </info_things>
    <things>
        <xsl:for-each select="//thing">
            <thing thing_id="{position()}" ref_id="{position()}">line</thing>
        </xsl:for-each>
    </things>
</XML>
</xsl:template>
</xsl:stylesheet>

And it outputs:

<?xml version="1.0" encoding="UTF-8"?>
<XML>
<ids>
    <id id="1" nr="10"/>
    <id id="2" nr="20"/>
    <id id="3" nr="30"/>
    <id id="4" nr="40"/>
</ids>
<info_things>
    <thing thing_id="1" id1="1" id2="2"/>
    <thing thing_id="2" id1="3" id2="4"/>
    <thing thing_id="3" id1="5" id2="6"/>
    <thing thing_id="4" id1="7" id2="8"/>
</info_things>
<things>
    <thing thing_id="1" ref_id="1">line</thing>
    <thing thing_id="2" ref_id="2">line</thing>
    <thing thing_id="3" ref_id="3">line</thing>
    <thing thing_id="4" ref_id="4">line</thing>
</things>
</XML>

This still has problems with the number of id's not being duplicated and the thing_id's in not being unique. I understand that id nr's also cannot probably be generated by simple positions when the id's are working. I tried declaring variables, but that didn't really help.

Thank you!

UPDATE:

I realised that I had forgot one pattern I tried to achieve. So ideally I would have in id nr's pattern:

<id id="1" nr="0"/>
<id id="2" nr="10"/>
<id id="3" nr="10"/>
<id id="4" nr="20"/>
<id id="5" nr="20"/>
<id id="6" nr="30"/>
<id id="7" nr="30"/>
<id id="8" nr="40"/>

Sorry for this! The answer of Lingamurthy CS does everything I asked for, thanks a lot!

回答1:

With a little modification. 1. Used xs:integer to type cast count to integer and iterating for //thing number of counts to generate "id"s, and using position()-1 to get the nr starting from 0. 2. Adding position() with count(//thing) to continue thing_id.

<?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 method="xml" omit-xml-declaration="no" />
<xsl:template match="/">
    <XML>
        <ids>
            <xsl:for-each select="1 to xs:integer(count(//thing) * 2)">
                <id id="{position()}" nr="{(position() - 1)*10}"/>
            </xsl:for-each>
        </ids>
        <info_things>
            <xsl:for-each select="//thing">
                <thing thing_id="{position()}" id1="{position()*2-1}" id2="{position()*2}"/>
            </xsl:for-each>
        </info_things>
        <things>
            <xsl:for-each select="//thing">
                <thing thing_id="{position() + count(//thing)}" ref_id="{position()}">line</thing>
            </xsl:for-each>
        </things>
    </XML>
</xsl:template>
</xsl:stylesheet>


标签: xml xslt