[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
[Recent Entries]
[Reply To This Message]
Re: saxon:evaluate() in schematron
Subject: Re: saxon:evaluate() in schematron
From: "Imsieke, Gerrit, le-tex" <gerrit.imsieke@xxxxxxxxx>
Date: Mon, 21 May 2012 23:37:38 +0200
|
Wendell, Matt,
I recently came across this blog post by Rick Jelliffe, Do you need to
make your own XSLT2 function definitions when using Schematron?
http://broadcast.oreilly.com/2010/09/do-you-need-to-make-your-own-x.html
Although it is tempting for XSLT2 pundits to introduce user-defined
functions in their Schematrons, Ricks post has made me resist this
temptation every time since I read it. If only for the reason that
without user-defined XSLT functions, Schematron schemas are more
portable, as weve seen today.
Rick also proposes let as a tool to break up iterations or, as in
Matts example, complex expressions.
Ive reworked my solution using let:
<s:rule context="line">
<s:let name="outliers" value="
for $att in
(@x1, @x2)[
xs:integer(.) gt
xs:integer(../../../block[@n eq current()/@n]/@x2)
or
xs:integer(.) lt
xs:integer(../../../block[@n eq current()/@n]/@x1)
]
union
(@y1, @y2)[
xs:integer(.) gt
xs:integer(../../../block[@n eq current()/@n]/@y2)
or
xs:integer(.) lt
xs:integer(../../../block[@n eq current()/@n]/@y1)
]
return concat(name($att), '=', $att)
"/>
<s:report test="exists($outliers)">
Line <s:value-of select="@n"/> does not fit.
Offending coordinate(s): <s:value-of select="$outliers" />
</s:report>
</s:rule>
Gerrit
On 2012-05-21 23:17, Wendell Piez wrote:
Matt,
Of course, I forgot that you'll probably want, or need, the function
also to say as="xs:boolean". (And who knows what else.)
Cheers,
Wendell
On 5/21/2012 5:12 PM, Wendell Piez wrote:
Hey Matt,
I'd actually consider using templates together with your function in
this case, to take advantage of the sort-of "dynamic dispatch" of
template matching:
So:
<xsl:function name="check-coord">
<xsl:param name="c" as="attribute()"/>
<xsl:param name="b" as="element(block)"/>
<xsl:apply-templates select="$c" mode="coord-check">
<xsl:with-param name="block" select="$b"/>
</xsl:apply-templates>
</xsl:function>
<!-- note that you can bind the return type of a template too -->
<xsl:template match="@x1" mode="coord-check" as="xs:boolean">
<xsl:param name="block" required="yes"/>
<xsl:sequence select="(number(.) >= number($block/@x1)) and
(number(.) <= number($block/@x2))"/>
</xsl:template>
etc. (one for each).
Then you can call the function in your XPath for all the coordinates
together and report just those that are broken:
test="every $c in (@x1, @x2, @y1, @y2) satisfies f:check-coord($c)">
Please check
<value-of select="string-join(
(@x1, @x2, @y1, @y2)[not(f:check-coord(.))]/name(),', ')"/>
Not tested, and I hope I've read your requirement correctly. :-)
Cheers,
Wendell
On 5/21/2012 4:05 PM, Matthew Stoeffler wrote:
Because there is value in returning the name of the coordinate that is
forcing the line out of the containing block box, not just that the
line is out of the box as a whole.
m./
On May 21, 2012, at 3:11 PM, Imsieke, Gerrit, le-tex wrote:
Why use evaluate when you can specify the assertion in a reasonably
simple XPath expression?
<s:rule context="line">
<s:assert test="every $coord in (@x1, @x2) satisfies
(
xs:integer($coord) le
xs:integer(../../block[@n eq current()/@n]/@x2)
and
xs:integer($coord) ge
xs:integer(../../block[@n eq current()/@n]/@x1)
)
and
(
every $coord in (@y1, @y2) satisfies
(
xs:integer($coord) le
xs:integer(../../block[@n eq current()/@n]/@y2)
and
xs:integer($coord) ge
xs:integer(../../block[@n eq current()/@n]/@y1)
)
)"
id="non-fitting-line">Line<s:value-of select="@n"/> does not
fit.</s:assert>
</s:rule>
Gerrit
On 2012-05-21 19:48, Matthew Stoeffler wrote:
Hello.
I'm working on a schematron script (iso schematron) in which I'm
trying to confirm a relationship between two elements representing
containing boxes. So, source xml looks like
<ref id="r7">
<label>5</label>
<block n="10" page="p-65" x1="579" y1="4604" x2="2634" y2="4682"/>
<citation id="c19" citation-type="other">
<line n="10" page="p-65" x1="1690" y1="4604" x2="2612"
y2="4682"><![CDATA[Walther Straram, Paris, 193I]]></line>
</citation>
</ref>
. and the relationship I'm looking for is whether the line (or
lines) are within the block, and, most frustratingly, which
coordinates are at fault if it doesn't fit.
My schematron pattern uses one function to ascertain whether or not
the line fits, and, if not, attempts to run the 'reportBadCoords'
function to identify which coordinates fail. The function looks like
this
<xsl:function name="ins:reportBadCoords" as="xs:string">
<xsl:param name="coordNode" as="node()"/>
<xsl:param name="coordName" as="xs:string"/>
<xsl:param name="blockPath" as="xs:string"/>
<xsl:param name="context" as="node()"/>
<xsl:variable as="xs:string" name="blkCoordPath"
select="concat('/',$blockPath,'/@',$coordName)"/>
<xsl:choose>
<xsl:when test="$coordName = 'x1'
and number(saxon:evaluate(concat('$p1',$blkCoordPath),$context))<
number($coordNode)"><xsl:value-of select="$coordName"/></xsl:when>
<xsl:when test="$coordName = 'x2'
and number(saxon:evaluate(concat('$p1',$blkCoordPath),$context))>
number($coordNode)"><xsl:value-of select="$coordName"/></xsl:when>
<xsl:when test="$coordName = 'y1'
and number(saxon:evaluate(concat('$p1',$blkCoordPath),$context))<
number($coordNode)"><xsl:value-of select="$coordName"/></xsl:when>
<xsl:when test="$coordName = 'y2'
and number(saxon:evaluate(concat('$p1',$blkCoordPath),$context))>
number($coordNode)"><xsl:value-of select="$coordName"/></xsl:when>
<!-- debugging -->
<xsl:otherwise><xsl:value-of
select="concat(saxon:evaluate(concat('$p1',$blkCoordPath),$context),'::',$coordName,'::',$blkCoordPath,'::',$coordNode)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
and is invoked from this rule.
<rule context="line">
<let name="lineNo" value="@n"/>
<let name="refId" value="ancestor::ref/@id"/>
<let name="artId"
value="ancestor::article/front/article-meta/article-id[@pub-id-type='doi']"/>
<assert test="some $bl in ancestor::ref/block
satisfies(ins:isContainedInBlock($bl, .))">
The current citation line (number:<value-of select="$lineNo"/> )
does not fit within any of the defined blocks in the containing ref
(ref id =<value-of select="$refId"/>).
[article id =<value-of select="$artId"/>].
Bad coords:
<value-of select="for $coord in @*[matches(name(),'[xy][12]')]
return
ins:reportBadCoords($coord,name($coord),functx:path-to-node-with-pos(ancestor::ref/block),current())"/>
</assert>
</rule>
When I test this script in Oxygen 13.2, with Saxon PE 9.305, I
either fail to return any value from the evaluate() function, or if
I remove the reference to context and just pass $blkCoordPath
straight to evaluate(), I get message that I'm selecting root node
without proper context, or context undefined.
Thanks for any help.
Matt S.
--
Gerrit Imsieke
Geschdftsf|hrer / Managing Director
le-tex publishing services GmbH
Weissenfelser Str. 84, 04229 Leipzig, Germany
Phone +49 341 355356 110, Fax +49 341 355356 510
gerrit.imsieke@xxxxxxxxx, http://www.le-tex.de
Registergericht / Commercial Register: Amtsgericht Leipzig
Registernummer / Registration Number: HRB 24930
Geschdftsf|hrer: Gerrit Imsieke, Svea Jelonek,
Thomas Schmidt, Dr. Reinhard Vvckler

|
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format
RSS 2.0 |
|
Atom 0.3 |
|
|