I have got lists with two types of list markers, namely numeric (1., 2., 3., etc.) and alphabetic [a), b), c), etc. or aa), bb), cc), etc.]. I want to check whether each item of a list is numbered subsequently according to its list marker type.
This means in numeric lists a subsequent item should be numbered as n+1 plus a dot, where n is the number in the current item's term and n+1 would be the number in its following-sibling::*[1]/self::item/term
.
In alphabetic lists the following-sibling::*[1]/self::item/term
should contain the next letter(s) in alphabetical order from the current item/term plus a closing parenthesis. So for example after "b)" would follow "c)" and after "cc)" would follow "dd)".
I do not want to change the numbering using xsl:number
, but just check and document the errors found and ideally their locations.
The input format would look like this:
<list>
<item>
<term>1.</term>
<p>jhjhjh hjkjkjkj</p>
</item>
<item>
<term>3.</term>
<p>jhjhjh hjkjkjkj</p>
</item>
<item>
<term>4.</term>
<p>jhjhjh hjkjkjkj</p>
</item>
</list>
Or:
<list>
<item>
<term>a)</term>
<p>jhjhjh hjkjkjkj</p>
</item>
<item>
<term>b)</term>
<p>jhjhjh hjkjkjkj</p>
</item>
<item>
<term>d)</term>
<p>jhjhjh hjkjkjkj</p>
</item>
</list>
Or:
<list>
<item>
<term>aa)</term>
<p>jhjhjh hjkjkjkj</p>
</item>
<item>
<term>cc)</term>
<p>jhjhjh hjkjkjkj</p>
</item>
<item>
<term>dd)</term>
<p>jhjhjh hjkjkjkj</p>
</item>
</list>
These input samples deliberately contain errors that should be detected and located.
Seems like a task for Schematron e.g.
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt3">
<pattern>
<rule context="item[term[matches(., '^[0-9]+\.$')]][position() gt 1]">
<assert test="
let $number := term => substring-before('.') => xs:integer(),
$number2 := preceding-sibling::item[1]/term => substring-before('.') => xs:integer()
return $number = $number2 + 1">item with <value-of select="term"/> doesn't have the right number.</assert>
</rule>
</pattern>
</schema>
For your alphabetic schema perhaps the following
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt3">
<pattern>
<rule context="item[term[matches(., '^[0-9]+\.$')]][position() gt 1]">
<assert test="
let $number := term => substring-before('.') => xs:integer(),
$number2 := preceding-sibling::item[1]/term => substring-before('.') => xs:integer()
return $number = $number2 + 1">item with <value-of select="term"/> doesn't have the right number.</assert>
</rule>
<rule context="item[term[matches(., '^[a-z]+\)$')]][position() gt 1]">
<assert test="
let $index := term => substring-before(')') => string-to-codepoints(),
$index2 := preceding-sibling::item[1]/term => substring-before(')') => string-to-codepoints()
return every $bool in for-each-pair($index, $index2, function($a, $b) { $a = $b + 1 }) satisfies $bool">item with <value-of select="term"/> doesn't have the right term.</assert>
</rule>
</pattern>
</schema>
helps, sample fiddle is online.
As for the error with Schxslt2, I think it is a bug in the template schxslt:failed-assertion-content
of transpile.xsl
that can be fixed as
<xsl:template name="schxslt:failed-assertion-content" as="node()+">
<xsl:sequence select="@flag"/>
<xsl:sequence select="@id"/>
<xsl:sequence select="@role"/>
<xsl:attribute name="test" select="@test => replace('\{', '{{') => replace('\}', '}}')"/>
<xsl:attribute name="xml:lang" select="schxslt:in-scope-language(.)"/>
<alias:attribute name="location" select="{($schxslt:location-function, 'path')[1]}(.)" xsl:use-when="not($schxslt:streamable) or exists($schxslt:location-function)"/>
<xsl:call-template name="schxslt:report-diagnostics"/>
<xsl:call-template name="schxslt:report-properties"/>
<xsl:call-template name="schxslt:report-message"/>
</xsl:template>
Bug is already fixed in Schxslt2 1.2.2, I have incorporated that version as an option in the Schematron fiddle, the sample now works.