I am looking to find a way to control both start and end numbering that are added as suffix number to text "period". It seems the logic of my code makes for-each
count 3 search matches (index 1-3), and due to using if
to find se:Bank
it reduces printout to 2 prints.
I know I can use position() -2
to force the numbering to start at 0, but that will only work if I have exact same amount of data. As soon as data growths the position() -2
will assume to step 2 positions minus and will not return zero as start.
I do understand that XSLT does what I actually ask for and returns presumable correct answer.
The interval of number I will be using is between 0 and 3. Most of the time in sequence. It will be unknown in advance exact interval amounts.
I know there is a start-at
using <xsl:number>
but it did not solve my problem. Using start-at
prints out same number twice.
The JSON file is aligned with a certain standard so I am not allowed to change the structure of the JSON file.
Suspected problem:
The "foreach" spans over more loops than wanted. In this case I need just for the system to loop twice for "se:Bank" and therefor return "period0" and "period1".
Observation:
I suspect that it probably would be better that I learn to extract when xbrl:concept = se:Bank
. That would reduce the planned loop down to 2 search, thus being able iterate over them.
Here you find the xsltfiddle.
Below you find same code as in xsltfiddle:
JSON data:
<data>
{
"report": {
"facts": [
{
"xbrl:concept": "se:CompanyName",
"value": "Great Company Ltd"
},
{
"xbrl:concept": "se:Bank",
"numericValue": 1000
},
{
"xbrl:concept": "se:Bank",
"numericValue": 3000
}
]
}
}
</data>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xhtml" indent="yes" html-version="5"/>
<xsl:mode on-no-match="shallow-skip"/>
<!-- Parse JSON to XML -->
<xsl:template match="data">
<xsl:apply-templates select="json-to-xml(.)/*"/>
</xsl:template>
<!-- Printout periods -->
<xsl:template match="//*[@key='facts']">
<xsl:for-each select="//*[@key='xbrl:concept']">
<xsl:if test=". = 'se:Bank'">
period<xsl:number value="position()"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Result:
<?xml version="1.0" encoding="UTF-8"?>period2period3
Expected result:
<?xml version="1.0" encoding="UTF-8"?>period0period1
If you want to output position()
or position() - 1
then <xsl:value-of select="position()"/>
or <xsl:value-of select="position() -1 "/>
, respectively, suffice, there is no need to feed position()
to xsl:number
.
Furthermore, I am not sure I understand your requirements correctly, but using a predicate <xsl:for-each select=".//*[@key='xbrl:concept'][. = 'se:Bank']">
instead of the of the nested xsl:if
should help to get the result you want, namely to process the two elements in the input sample meeting the condition in the predicate: https://xsltfiddle.liberty-development.net/93wniUS/1