Relax NG:table

S

slitvinov

I am learning Relax NG. The problem is that I cannot figure
out how to make a schema for a table.
In my case I would like to make a table with any name of child
elements (columns) but columns should have the same number of
child elements (cell). Say this file is valid
<table>
<column>
<cell/>
<cell/>
</column>
<column>
<cell/>
<cell/>
</column>
<table/>

but this one is not
<table>
<column>
<cell/>
<cell/>
</column>
<column>
<cell/>
</column>
<table/>

Thank you in advance.
 
S

Soren Kuula

I am learning Relax NG. The problem is that I cannot figure
out how to make a schema for a table.
In my case I would like to make a table with any name of child
elements (columns) but columns should have the same number of
child elements (cell). Say this file is valid

That's not expressible as a regular tree language, so Relax NG can't
express it either. In fact, no schema language that I know of can
express it.

Soren
 
G

George Bina

You can use Schematron embedded rules for that. See below a full
sample:

<?xml version="1.0" encoding="UTF-8"?>
<grammar ns="" xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:sch="http://www.ascc.net/xml/schematron">
<start>
<element name="table">
<oneOrMore>
<element name="column">
<sch:pattern name="Check to have the same number of cells in
each column" id="cells">
<sch:rule context="column">
<sch:assert test="count(../column[1]/cell) =
count(cell)">The number of cells in this
column should be the same as in the firtst column,
expected <sch:value-of
select="count(../column[1]/cell)"/> but got
<sch:value-of select="count(cell)"/>.
</sch:assert>
</sch:rule>
</sch:pattern>
<oneOrMore>
<element name="cell">
<empty/>
</element>
</oneOrMore>
</element>
</oneOrMore>
</element>
</start>
</grammar>

On your second document (after you make it wellformed) you will get:

The number of cells in this column should be the same as in the firtst
column, expected 2 but got 1 . (count(../column[1]/cell) = count(cell))

Best Regards,
George
 
P

Philippe Poulard

Soren said:
That's not expressible as a regular tree language, so Relax NG can't
express it either. In fact, no schema language that I know of can
express it.

Soren

hi,

you should consider an alternate schema technology, such as Active Schema :

the schema :
====================== schema.asl
<?xml version="1.0" encoding="iso-8859-1" ?>
<asl:active-schema
xmlns:xcl="http://www.inria.fr/xml/active-tags/xcl"
xmlns:asl="http://www.inria.fr/xml/active-schema"
xmlns:xs="http://www.w3.org/2001/XMLSchema-datatypes"
target=""
<asl:element name="test" root="always">
<asl:sequence>
<asl:element ref-elem="table" min-occurs="0"
max-occurs="unbounded"/>
</asl:sequence>
</asl:element>

<asl:element name="table">
<asl:sequence>
<asl:element ref-elem="column" min-occurs="1"
max-occurs="unbounded"/>
</asl:sequence>
</asl:element>

<asl:element name="column">
<asl:sequence>
<xcl:if test="{ asl:element()/preceding-sibling::column }">
<xcl:then>
<asl:element ref-elem="cell" min-occurs="{
$asl:max-occurs }" max-occurs="{ count( asl:element()/../column[1]/cell
) }"/>
</xcl:then>
<xcl:else>
<asl:element ref-elem="cell" min-occurs="1"
max-occurs="unbounded"/>
</xcl:else>
</xcl:if>
</asl:sequence>
</asl:element>

</asl:active-schema>
=====================
as you might guess, the Active Schema Language differs slightly from
other schema technologies : most things that are usually hard-coded in
the schema can be defined contextually
-boundaries can be computed dynamically
-content models can also be computed dynamically
-you can mix declarative sentences with imperative instructions
-the specification defines only 20 tags
-and much more...

notice that unlike schematron, ASL computes content models, which allows
tools such as editors to predict which element is allowed ; schematron
is not predictive, it can only warn that a rule has not been followed
AFTER the user has made the mistake, for example by inserting an element
that is not allowed

the datas :
===================== datas.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<test>

<!--good-->
<table>
<column>
<cell/>
<cell/>
</column>
<column>
<cell/>
<cell/>
</column>
</table>
<table>
<column>
<cell/>
<cell/>
<cell/>
</column>
<column>
<cell/>
<cell/>
<cell/>
</column>
<column>
<cell/>
<cell/>
<cell/>
</column>
</table>

<!--bad-->
<table>
<column>
<cell/>
<cell/>
</column>
<column>
<cell/><!--cell missing-->
</column>
</table>
<table>
<column>
<cell/>
<cell/>
</column>
<column>
<cell/>
<cell/>
</column>
<column>
<cell/>
<cell/>
<cell/><!--too much cell-->
</column>
<column>
<cell/><!--cell missing-->
</column>
</table>
<table>
<!--no column ???-->
<cell/><!--oops-->
<cell/><!--oops-->
</table>

</test>
==========================

the Active Sheet which validates the datas with the schema :
============================== active-sheet.xcl
<?xml version="1.0" encoding="iso-8859-1"?>
<xcl:active-sheet
xmlns:xcl="http://www.inria.fr/xml/active-tags/xcl"
xmlns:asl="http://www.inria.fr/xml/active-schema"
<xcl:parse name="datas" source="datas.xml"/>
<asl:parse-schema name="schema" source="schema.asl"/>

<asl:validate schema="{ $schema }" node="{ $datas }" augment="yes"
deep="yes" report="report"/>

<xcl:for-each name="err" select="{ $report/* }">
<xcl:echo value="Error { name( value( $err/@reason-id ) ) }"/>
<xcl:echo value=" node : { value( $err/@path/@path ) }"/>
<xcl:echo value=" rule : { value(
$err/@rule-path/@rule-path ) }"/>
</xcl:for-each>

</xcl:active-sheet>
=====================
you see unusual XPath expressions above, because Active Tags allow to
use XPath on non-XML object, which is the case of "$err" : an object can
expose some properties as attributes, which value can be an object can
expose some properties as attributes, which explain why $err/@path/@path
is relevant

the output :
=====================
Error asl:elementExpected
node : {/test/table[3]/column[2]/}
rule :
{/asl:active-schema/asl:element[3]/asl:sequence/xcl:if/xcl:then/asl:element}
Error asl:noMoreContentAllowed
node : {/test/table[4]/column[3]/cell[3]}
rule : {/asl:active-schema/asl:element[3]}
Error asl:elementExpected
node : {/test/table[4]/column[4]/}
rule :
{/asl:active-schema/asl:element[3]/asl:sequence/xcl:if/xcl:then/asl:element}
Error asl:elementExpected
node : {/test/table[5]/cell[1]}
rule : {/asl:active-schema/asl:element[2]/asl:sequence/asl:element}
Error asl:noMoreContentAllowed
node : {/test/table[5]/cell[1]}
rule : {/asl:active-schema/asl:element[2]}
Error asl:noMoreContentAllowed
node : {/test/table[5]/cell[2]}
rule : {/asl:active-schema/asl:element[2]}

======================
the detailed specification :
http://disc.inria.fr/perso/philippe.poulard/xml/active-tags/active-schema/active-schema.html

the tool that implement all that stuff :
http://reflex.gforge.inria.fr/

you can download RefleX freely and run the given Active Sheet to check
the XML datas with the Active Schema


--
Cordialement,

///
(. .)
--------ooO--(_)--Ooo--------
| Philippe Poulard |
 
S

slitvinov

Thank you everyone.
And I am sorry about the typo in the example.

I actually use emacs nxml mode to create XML files by hands. nxml mode
uses RELAX NG and the sample given by George can be used for validation
(it is already very helpful for me). But it seems in this case it would
not be predictive (as Philippe pointed out).

I am wondering is there any editor or emacs mode based on Active
Schema?
 
P

Philippe Poulard

Thank you everyone.
And I am sorry about the typo in the example.

I actually use emacs nxml mode to create XML files by hands. nxml mode
uses RELAX NG and the sample given by George can be used for validation
(it is already very helpful for me). But it seems in this case it would
not be predictive (as Philippe pointed out).

I am wondering is there any editor or emacs mode based on Active
Schema?

sorry, not yet : it is somewhat experimental :)

--
Cordialement,

///
(. .)
--------ooO--(_)--Ooo--------
| Philippe Poulard |
 
G

George Bina

Hmm, I do not understand what can be predicetd here. The column element
contains cell and that's all. Assumming you have a table with 2 columns
and each column with 3 cells. Now if you want to have 4 cells in each
column no matter where you start you will pass through an invalid state
so would you prefer to have no hints than to have cell offered as
possible entry inside column?

Best Regards,
George
 
P

Philippe Poulard

This is an interesting remark : it seems preferable for an editor to
*suggest* rather than to *force* ; thus, the user would be allowed to
leave a valid state.

I thought that the first <column> could be taken as the model for the
rest of the <table>, but there is certainly a better strategy to compute
the boundaries :
-if there is a single <column>,
min-occurs=0 (or 1 ?)
max-occurs=unbounded
-if there are several <column>s :
min-occurs=max(number of <cell>s in the other <column>s)
max-occurs=min(number of <cell>s in the other <column>s)
So, considering a <column>, the others are "the reference", and you are
*suggested* to converge, either by deleting or adding <cell>s, until all
the <column>s have the same number of <cell>s ; however, even if you are
not suggested to add a new <cell>, you are *allowed* to do so anyway.

This is strange because having min-occurs > max-occurs is possible ; for
the moment I was reporting this case as an error in the schema, but I
could reconsider this (maybe by reporting a warning instead), as it's
only a case where some conditions are not met and can be corrected in
many actions.

I'm still convinced that defining content models dynamically increases
significantly the expressiveness of schemata. This is the power of
Active Schema.

George said:
Hmm, I do not understand what can be predicetd here. The column element
contains cell and that's all. Assumming you have a table with 2 columns
and each column with 3 cells. Now if you want to have 4 cells in each
column no matter where you start you will pass through an invalid state
so would you prefer to have no hints than to have cell offered as
possible entry inside column?

Best Regards,
George


--
Cordialement,

///
(. .)
--------ooO--(_)--Ooo--------
| Philippe Poulard |
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,001
Messages
2,570,255
Members
46,852
Latest member
CarlaDowle

Latest Threads

Top