Figure 1: Abstract call graph for the core layer
ELEMID ::= [element(N:GI,Lras,Lre)],
{
sva_atts_TYPEID(Lras,Lpa,Lpna),
sva_content_TYPEID(Lre,Lpe)
}
<:> info_item(element)
&& attributes(Lpa)
&& namespace_attributes(Lpna)
&& children(Lpe)
&& local_name(GI)
&& namespace_name(N)
&& type_definition_anonymous(Boolean)
&& type_definition_namespace(URI)
&& type_definition_name(NCName)
&& type_definition_type(complex)
&& validation_attempted(full)
&& validity(valid)
.
Later, we will add further grammatical attributes, and
use values other than full and valid
for invalid elements.
/* e_purchaseOrder: grammatical rule for purchaseOrder element.
e_purchaseOrder(ParsedNode,L1,L2): holds if the difference
between L1 and L2 (difference lists) is a purchase order
element in SWI Prolog notation.
And so on for the other element types.
*/
e_purchaseOrder ::= [
element('http://www.example.com/PO1':purchaseOrder,
Lras,Lre)],
{
sva_atts_t_PurchaseOrderType(Lras,Lpa,Lpna),
sva_content_t_PurchaseOrderType(Lre,Lpe)
}
<:> local_name(purchaseOrder)
&& namespace_name('http://www.example.com/PO1')
&& type_definition_anonymous('false')
&& type_definition_namespace('http://www.example.com/PO1')
&& type_definition_name('PurchaseOrderType')
&& type_definition_type(complex)
{Common infoset properties for elements in po namespace 2}
.
e_shipTo_t_PurchaseOrderType ::= [element(shipTo,Lras,Lre)],
{
sva_atts_t_USAddress(Lras,Lpa,Lpna),
sva_content_t_USAddress(Lre,Lpe)
}
<:> local_name(shipTo)
&& namespace_name('')
&& type_definition_anonymous('false')
&& type_definition_namespace('http://www.example.com/PO1')
&& type_definition_name('USAddress')
&& type_definition_type(complex)
{Common infoset properties for elements in po namespace 2}
.
e_billTo_t_PurchaseOrderType ::= [element(billTo,Lras,Lre)],
{
sva_atts_t_USAddress(Lras,Lpa,Lpna),
sva_content_t_USAddress(Lre,Lpe)
}
<:> local_name(billTo)
&& namespace_name('')
&& type_definition_anonymous('false')
&& type_definition_namespace('http://www.example.com/PO1')
&& type_definition_name('USAddress')
&& type_definition_type(complex)
{Common infoset properties for elements in po namespace 2}
.
e_items_t_PurchaseOrderType ::= [element(items,Lras,Lre)],
{
sva_atts_t_Items(Lras,Lpa,Lpna),
sva_content_t_Items(Lre,Lpe)
}
<:> local_name(items)
&& namespace_name('')
&& type_definition_anonymous('false')
&& type_definition_namespace('http://www.example.com/PO1')
&& type_definition_name('Items')
&& type_definition_type(complex)
{Common infoset properties for elements in po namespace 2}
.
e_item_t_Items ::= [element(item,Lras,Lre)],
{
sva_atts_t_e_item_t_Items(Lras,Lpa,Lpna),
sva_content_t_e_item_t_Items(Lre,Lpe)
}
<:> local_name(item)
&& namespace_name('')
&& type_definition_anonymous('true')
&& type_definition_namespace('http://www.example.com/PO1')
&& type_definition_name('t_e_item_t_Items')
&& type_definition_type(complex)
{Common infoset properties for elements in po namespace 2}
.
&& info_item(element) && attributes(Lpa) && namespace_attributes(Lpna) && children(Lpe) && validation_attempted(full) && validity(valid)
e_comment ::=
[element('http://www.example.com/PO1':comment,Lras,Lre)],
{Guard to check attributes and content of strings 4}
<:> local_name(comment)
&& namespace_name('http://www.example.com/PO1')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for strings 5}
.
e_name_t_USAddress ::= [element(name,Lras,Lre)],
{Guard to check attributes and content of strings 4}
<:> local_name(name)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for strings 5}
.
e_street_t_USAddress ::= [element(street,Lras,Lre)],
{Guard to check attributes and content of strings 4}
<:> local_name(street)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for strings 5}
.
e_city_t_USAddress ::= [element(city,Lras,Lre)],
{Guard to check attributes and content of strings 4}
<:> local_name(city)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for strings 5}
.
e_state_t_USAddress ::= [element(state,Lras,Lre)],
{Guard to check attributes and content of strings 4}
<:> local_name(state)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for strings 5}
.
e_zip_t_USAddress ::= [element(zip,Lras,Lre)],
{
sva_atts_simpletype(Lras,Lpa,Lpna),
sva_content_t_xsd_decimal(Lre,Lpe)
}
<:> local_name(zip)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for decimals 6}
.
e_productName_t_e_item_t_Items ::= [element(productName,
Lras,Lre)],
{Guard to check attributes and content of strings 4}
<:> local_name(productName)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for strings 5}
.
e_quantity_t_e_item_t_Items ::= [element(quantity,
Lras,Lre)],
{
sva_atts_simpletype(Lras,Lpa,Lpna),
sva_content_t_e_quantity_t_e_item_t_Items(Lre,Lpe)
}
<:> local_name(quantity)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
&& type_definition_anonymous('true')
&& type_definition_namespace('http://www.example.com/PO1')
&& type_definition_name('t_e_quantity_t_e_item_t_Items')
&& type_definition_type(simple)
.
e_USPrice_t_e_item_t_Items ::= [element('USPrice',Lras,Lre)],
{
sva_atts_simpletype(Lras,Lpa,Lpna),
sva_content_t_xsd_decimal(Lre,Lpe)
}
<:> local_name('USPrice')
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
{PSVI properties for decimals 6}
.
e_shipDate_t_e_item_t_Items ::= [element(shipDate,Lras,Lre)],
{
sva_atts_simpletype(Lras,Lpa,Lpna),
sva_content_t_xsd_date(Lre,Lpe)
}
<:> local_name(shipDate)
&& namespace_name('')
{Common infoset properties for elements in po namespace 2}
&& type_definition_anonymous('false')
&& type_definition_namespace(
'http://www.w3.org/2001/XMLSchema')
&& type_definition_name('date')
&& type_definition_type(simple)
.
{
sva_atts_simpletype(Lras,Lpa,Lpna),
sva_content_t_xsd_string(Lre,Lpe)
}
&& type_definition_anonymous('false')
&& type_definition_namespace(
'http://www.w3.org/2001/XMLSchema')
&& type_definition_name('string')
&& type_definition_type(simple)
&& type_definition_anonymous('false')
&& type_definition_namespace(
'http://www.w3.org/2001/XMLSchema')
&& type_definition_name('decimal')
&& type_definition_type(simple)
sva_atts_TYPEID(Lras,Lpa,Lpna) :- lras_TYPEID(LpaAll,Lras,[]), /* parse w/ grammar */ partition(LpaAll,LpaPresent,Lpna), /* partition result */ attocc_TYPEID(LpaPresent,Lpa). /* check min, max rules */The logical variables have the following meanings:
lras_dt ::= [].
lras_dt ::= ras_dt, lras_dt. /* declared attributes */
lras_dt ::= ras_nsd, lras_dt. /* namespace declarations */
lras_dt ::= ras_xsi, lras_dt. /* XSI attributes */
ras_dt ::= [an1=Av], { sva_plf_st1(Av) }.
ras_dt ::= [an2=Av], { sva_plf_st2(Av) }.
Simple types will, of course, have no declared attributes, and
the rules for declared attributes and occurrence-checking
(together with the rules for individual attributes) will be omitted.
Wildcard support can also be added here when needed.
/* ras_nsd: grammatical rule for namespace-attribute
* specifications */
ras_nsd ::= [xmlns=DefaultNS]
<:> info_item(attribute)
&& local_name(xmlns)
&& namespace_name('http://www.w3.org/2000/xmlns/')
&& normalized_value(DefaultNS)
&& prefix('##NONE')
&& namespace(DefaultNS).
ras_nsd ::= [xmlns:Prefix=NSName]
<:> info_item(attribute)
&& local_name(Prefix)
&& namespace_name('http://www.w3.org/2000/xmlns/')
&& normalized_value(NSName)
&& prefix(Prefix)
&& namespace(NSName).
Continued in <Grammar rules for XSI attributes 8>
/* ras_xsi: grammar rule for XSI attribute specifications */
ras_xsi ::=
['http://www.w3.org/2001/XMLSchema-instance':type=Value],
{ sva_plf_t_xsd_qname(Value) }
<:> local_name(type)
&& type_definition_name('QName')
&& type_definition_anonymous('false')
{Common properties for xsi attributes 9}
ras_xsi ::=
['http://www.w3.org/2001/XMLSchema-instance':nil=Value],
{ sva_plf_t_xsd_boolean(Value) }
<:> local_name(nil)
&& type_definition_name('boolean')
&& type_definition_anonymous('false')
{Common properties for xsi attributes 9}
ras_xsi ::=
['http://www.w3.org/2001/XMLSchema-instance':schemaLocation=Value],
{ sva_plf_t_xsd_list_of_qname(Value) }
<:> local_name(schemaLocation)
&& type_definition_name('t_a_schemaLocation')
&& type_definition_anonymous('true')
{Common properties for xsi attributes 9}
ras_xsi ::=
['http://www.w3.org/2001/XMLSchema-instance':noNamespaceSchemaLocation=Value],
{ sva_plf_t_xsd_qname(Value) }
<:> local_name(noNamespaceSchemaLocation)
&& type_definition_name('QName')
&& type_definition_anonymous('false')
{Common properties for xsi attributes 9}
&& info_item(attribute)
&& namespace_name('http://www.w3.org/2001/XMLSchema-instance')
&& normalized_value(Value)
&& type_definition_namespace(
'http://www.w3.org/2001/XMLSchema')
&& type_definition_type(simple)
&& schema_specified(infoset)
&& validation_attempted(full)
&& validity(valid).
/* QName has no meaningful restrictions on lexical form, so we * don't check anything. Even the whitespace normalization is * pointless in the core grammar. */ sva_plf_t_xsd_qname(PLF) :- ws_normalize(collapse,PLF,_LF), atom(PLF). sva_plf_t_xsd_list_of_qname(PLF) :- ws_normalize(collapse,PLF,_LF), atom(PLF). sva_plf_t_xsd_boolean(PLF) :- ws_normalize(collapse,PLF,LF), atom_chars(LF,L), lexform_boolean(_,L,[]).
lexform_boolean ::= bool_true. lexform_boolean ::= bool_false. bool_true ::= ['1']. bool_true ::= [t], [r], [u], [e]. bool_false ::= ['0']. bool_false ::= [f], [a], [l], [s], [e].
attocc_dt(LpaPres,LpaAll) :- atts_present(LpaPres,Lreq), atts_absent(LpaPres,Lnot), atts_defaulted(LpaPres,Ldft,LpaAll).
/* atts_present(Lpa,Lreq): true if a parsed attribute node is present in Lpa for each attribute name in Lreq */ atts_present(_LRAS,[]). atts_present(LRAS,[HRA|RequiredTail]) :- att_present(LRAS,HRA), atts_present(LRAS,RequiredTail). /* An attribute name matches if namespace name and local * name part match */ /* att_present(Lpa,Attname): true if a parsed attribute node * is present in Lpa which has name Attname */ att_present([Pa|_Lpa],NS:Attname) :- Pa^^local_name(Attname), Pa^^namespace_name(NS). att_present([_Pa|Lpa],Attname) :- att_present(Lpa,Attname). /* no base step: if we reach att_present([],Attname) we want * to fail. */Continued in <Utility for checking absent attributes 13>, <Utility for providing defaulted attributes 14>
/* atts_absent(Lpa,Ltabu): true if no attribute named in * Ltabu is present in Lpa */ atts_absent(_LRAS,[]). atts_absent(LRAS,[H|T]) :- not(att_present(LRAS,H)), atts_absent(LRAS,T).
/* atts_defaulted(L1,L2,L3): true if L3 has all the * attributes in L1, plus all of the attributes in L2 which * are not also in L1 */ atts_defaulted(Lpa,[],Lpa). atts_defaulted(Lpa,[Padft|Ldft],LpaAll) :- atts_defaulted(Lpa,Ldft,Lpa2), att_merge(Lpa2,Padft,LpaAll).Continued in <Utility for providing defaulted attributes 15>
/* att_merge(L1,Pa,L2): if Pa is present in L1, then L3 = L1,
otherwise L3 = L1 + Pa. */
att_merge([],Padft,[Padft]).
att_merge([Pa|Lpa],Padft,[Pa|Lpa]) :-
nonvar(Pa), nonvar(Lpa), nonvar(Padft),
Pa^^namespace_name(NS),
Padft^^namespace_name(NS),
Pa^^local_name(Lnm),
Padft^^local_name(Lnm).
att_merge([Pa|Lpa],Padft,Lpa2) :-
nonvar(Pa), nonvar(Lpa), nonvar(Padft),
not( (Pa^^namespace_name(NS),
Padft^^namespace_name(NS),
Pa^^local_name(Lnm),
Padft^^local_name(Lnm) ) ),
att_merge(Lpa,Padft,Lpa2).
/* sva_atts_TYPENAME(Lras,Lpa,Lpna): true if Lras contains
* an input-form list of attribute specifications which
* is legal for complex type TYPENAME, and which
* corresponds to the list of parsed attributes Lpa plus
* the list of parsed namespace attributes Lpna. */
sva_atts_t_PurchaseOrderType(Lras,Lpa,Lpna) :-
lras_t_PurchaseOrderType(LpaAll,Lras,[]),
partition(LpaAll,Lpa,Lpna),
attocc_t_PurchaseOrderType(LpaPres,Lpa).
lras_t_PurchaseOrderType ::= []
{Grammatical attributes for empty attribute list 22}.
lras_t_PurchaseOrderType ::= ras_t_PurchaseOrderType^^Pa,
lras_t_PurchaseOrderType^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_t_PurchaseOrderType ::= ras_nsd^^Pa,
lras_t_PurchaseOrderType^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_t_PurchaseOrderType ::= ras_xsi^^Pa,
lras_t_PurchaseOrderType^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
ras_t_PurchaseOrderType ::= [orderDate=Value],
{ sva_plf_t_xsd_date(Value) }
{Properties for orderDate attribute 24}.
/* Literally copying the pattern would give us this:
attocc_t_PurchaseOrderType(LpaPres,LpaAll) :-
atts_present(LpaPres,[]),
atts_absent(LpaPres,[]),
atts_defaulted(LpaPres,[],LpaAll).
but that's pointless. Instead, we'll do the equivalent: */
attocc_t_PurchaseOrderType(L,L).
/* ws_normalize(Keyword,Input,Output): true if Output is * an atom identical to the whitespace-normalized form of * Input, with the whitespace mode indicated by Keyword. */ ws_normalize(preserve,Atom,Atom).Continued in <Utility for whitespace normalization 18>, <Utility for whitespace normalization 20>
ws_normalize(replace,In,Out) :- atom_codes(In,Lcin), ws_blanks(Lcin,Lcout), atom_codes(Out,Lcout).
/* ws_blanks(A,B): where A has any whitespace, B has a blank */ ws_blanks([],[]). ws_blanks([9|T1],[32|T2]) :- ws_blanks(T1,T2). ws_blanks([10|T1],[32|T2]) :- ws_blanks(T1,T2). ws_blanks([13|T1],[32|T2]) :- ws_blanks(T1,T2). ws_blanks([H|T1],[H|T2]) :- not(member(H,[9,10,13])), ws_blanks(T1,T2).
ws_normalize(collapse,In,Out) :- ws_normalize(replace,In,Temp), atom_codes(Temp,Lctemp), ws_collapse(Lctemp,Lcout), atom_codes(Out,Lcout).Continued in <Utility to change whitespace characters to blanks 19>, <Utility for collapsing whitespace 21>
/* ws_collapse(A,B): B is like A, with all strings of blanks * collapsed to single blanks, and leading and trailing * blanks stripped. */ /* ws_collapse/2 strips leading blanks, then calls * ws_collapse/3 */ ws_collapse([],[]). ws_collapse([32|T1],T2) :- ws_collapse(T1,T2). ws_collapse([H|T1],[H|T2]) :- not(H=32), ws_collapse(internal,T1,T2). /* ws_collapse/3 walks past non-blanks, and when it hits a * string of blanks, it drops all but the last one before * a non-blank. */ ws_collapse(internal,[],[]). ws_collapse(internal,[32],[]). ws_collapse(internal,[H|T1],[H|T2]) :- not(H=32), ws_collapse(internal,T1,T2). ws_collapse(internal,[32,32|T1],T2) :- ws_collapse(internal,[32|T1],T2). ws_collapse(internal,[32,H|T1],[32,H|T2]) :- not(H=32), ws_collapse(internal,T1,T2).
<:> attributes([])
<:> attributes([Pa|L]) ::- Lpa^^attributes(L)
<:> info_item(attribute)
&& local_name('orderDate')
&& namespace_name('')
&& normalized_value(Value)
&& type_definition_anonymous('false')
&& type_definition_namespace(
'http://www.w3.org/2001/XMLSchema')
&& type_definition_name('date')
&& type_definition_type(simple)
&& schema_specified(infoset)
&& validation_attempted(full)
&& validity(valid)
sva_atts_t_USAddress(Lras,Lpa,Lpna) :-
lras_t_USAddress(LpaAll,Lras,[]),
partition(LpaAll,LpaPres,Lpna),
attocc_t_USAddress(LpaPres,Lpa).
lras_t_USAddress ::= []
{Grammatical attributes for empty attribute list 22}.
lras_t_USAddress ::= ras_t_USAddress^^Pa,
lras_t_USAddress^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_t_USAddress ::= ras_nsd^^Pa, lras_t_USAddress^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_t_USAddress ::= ras_xsi^^Pa, lras_t_USAddress^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
ras_t_USAddress ::= [country='US']
<:> info_item(attribute)
&& local_name('country')
&& namespace_name('')
&& normalized_value('US')
&& type_definition_anonymous('false')
&& type_definition_namespace(
'http://www.w3.org/2001/XMLSchema')
&& type_definition_name('NMTOKEN')
&& type_definition_type(simple)
&& schema_specified(infoset)
&& validation_attempted(full)
&& validity(valid)
.
Continued in <Attribute occurrence checking for USAddress 26>
attocc_t_USAddress(LpaPresent,LpaAll) :-
CountryAtt = node(
attribute(country),
[],
[ (info_item(attribute)),
(namespace_name('')),
(local_name('country')),
(normalized_value('US')),
(type_definition_anonymous('false')),
(type_definition_namespace(
'http://www.w3.org/2001/XMLSchema')),
(type_definition_name('NMTOKEN')),
(type_definition_type(simple)),
(schema_specified(schema)),
(validation_attempted(full)),
(validity(valid))
]),
atts_defaulted(LpaPres,[CountryAtt],LpaAll).
sva_atts_t_Items(Lras,Lpa,Lpna) :-
lras_t_Items(LpaAll,Lras,[]),
partition(LpaAll,LpaPres,Lpna).
lras_t_Items ::= []
{Grammatical attributes for empty attribute list 22}.
lras_t_Items ::= ras_nsd^^Pa, lras_t_Items^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_t_Items ::= ras_xsi^^Pa, lras_t_Items^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
sva_atts_t_e_item_t_Items(Lras,Lpa,Lpna) :-
lras_t_e_item_t_Items(LpaAll,Lras,[]),
partition(LpaAll,LpaPres,Lpna),
attocc_t_e_item_t_Items(LpaPres,Lpa).
lras_t_e_item_t_Items ::= []
{Grammatical attributes for empty attribute list 22}.
lras_t_e_item_t_Items ::= ras_t_e_item_t_Items^^Pa,
lras_t_e_item_t_Items^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_t_e_item_t_Items ::= ras_nsd^^Pa,
lras_t_e_item_t_Items^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_t_e_item_t_Items ::= ras_xsi^^Pa,
lras_t_e_item_t_Items^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
Continued in <PartNum attribute 29>
ras_t_e_item_t_Items ::= [partNum=Value],
{ sva_plf_t_SKU(Value) }
<:> info_item(attribute)
&& local_name('partNum')
&& namespace_name('')
&& normalized_value(Value)
&& type_definition_anonymous('false')
&& type_definition_namespace(
'http://www.example.com/PO1')
&& type_definition_name('SKU')
&& type_definition_type(simple)
&& schema_specified(infoset)
&& validation_attempted(full)
&& validity(valid)
.
/* one required attribute: partNum */
attocc_t_e_item_t_Items(LpaPres,LpaAll) :-
atts_present(LpaPres,['':partNum]),
atts_absent(LpaPres,[]),
atts_defaulted(LpaPres,[],LpaAll).
sva_atts_simpletype(Lras,Lpa,Lpna) :-
lras_sT(LpaAll,Lras,[]),
partition(LpaAll,LpaPres,Lpna).
lras_sT ::= []
{Grammatical attributes for empty attribute list 22}.
lras_sT ::= ras_nsd^^Pa, lras_sT^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
lras_sT ::= ras_xsi^^Pa, lras_sT^^Lpa
{Grammatical attributes for attribute-list recursion 23}.
partition(LpaAll,LpaPresent,Lpna) :-
LpaAll^^attributes(L),
partition2(L,LpaPresent,Lpna).
partition2([],[],[]).
partition2([Pa|Lpa],LpaPres,[Pa|Lpna]) :-
Pa^^local_name(xmlns),
partition2(Lpa,LpaPres,Lpna).
partition2([Pa|Lpa],LpaPres,[Pa|Lpna]) :-
Pa^^namespace_name('http://www.w3.org/2000/xmlns/'),
partition2(Lpa,LpaPres,Lpna).
partition2([Pa|Lpa],[Pa|LpaPres],Lpna) :-
not(Pa^^local_name(xmlns)),
not(Pa^^namespace_name('http://www.w3.org/2000/xmlns/')),
partition2(Lpa,LpaPres,Lpna).
Pa^^namespace_name('http://www.w3.org/2000/xmlns/'),
to the rule for namespace attributes declaring default namespaces,
to avoid problems if xmlns were to appear as a
local name in some other namespace.
Since all names beginning with xml
are reserved, though, it would be illegal for xmlns
to appear in an application namespace (other than one defined
in the future by W3C), so I have not added this test.
content_t_PurchaseOrderType ::=
e_shipTo_t_PurchaseOrderType^^S,
e_billTo_t_PurchaseOrderType^^B,
opt_e_comment^^C,
e_items_t_PurchaseOrderType^^I
{Children attribute of t_PurchaseOrder 36}
.
opt_e_comment ::= []
{Empty list of children for opt_e_comment nonterminal 34}
.
opt_e_comment ::= e_comment^^Comm
{Children for opt_e_comment nonterminal 35}
.
content_t_USAddress ::=
e_name_t_USAddress^^N,
e_street_t_USAddress^^S,
e_city_t_USAddress^^C,
e_state_t_USAddress^^ST,
e_zip_t_USAddress^^Z
{Children attribute of t_USAddress 33}
.
content_t_Items ::= star_e_item_t_Items^^L
{Children attribute of content_t_Items 40}
.
star_e_item_t_Items ::= []
{Empty list of children for star_e_item_t_Items nonterminal 41}
.
star_e_item_t_Items ::=
e_item_t_Items^^I,
star_e_item_t_Items^^L
{Children for star_e_item_t_Items nonterminal 42}
.
content_t_e_item_t_Items ::=
e_productName_t_e_item_t_Items^^PN,
e_quantity_t_e_item_t_Items^^Q,
e_USPrice_t_e_item_t_Items^^USP,
opt_e_comment^^C,
opt_e_shipDate_t_e_item_t_Items^^S
{Children attribute of t_e_item_t_Items 37}
.
opt_e_shipDate_t_e_item_t_Items ::= []
{Empty list of children for opt_e_shipdate nonterminal 38}
.
opt_e_shipDate_t_e_item_t_Items ::=
e_shipDate_t_e_item_t_Items^^S
{Children for opt_e_shipdate nonterminal 39}
.
<:> children([N,S,C,ST,Z])
<:> children([])
<:> children([Comm])
<:> children(Lpe) ::-
C^^children(CC),
flatten([S,B,CC,I],Lpe)
<:> children(Lpe) ::-
C^^children(CC),
S^^children(SC),
flatten([PN,Q,USP,CC,SC],Lpe)
<:> children([])
<:> children([S])
<:> children(List) ::- L^^children(List)
<:> children([])
<:> children([I|T]) ::- L^^children(T)
sva_content_t_PurchaseOrderType(Lre,Lpe) :- content_t_PurchaseOrderType(Topnode,Lre,[]), Topnode ^^ children(Lpe). sva_content_t_USAddress(Lre,Lpe) :- content_t_USAddress(Topnode,Lre,[]), Topnode ^^ children(Lpe). sva_content_t_Items(Lre,Lpe) :- content_t_Items(Topnode,Lre,[]), Topnode ^^ children(Lpe). sva_content_t_e_item_t_Items(Lre,Lpe) :- content_t_e_item_t_Items(Topnode,Lre,[]), Topnode ^^ children(Lpe).
sva_content_t_xsd_string([PLF],[PLF]) :- sva_plf_t_xsd_string(PLF). sva_content_t_xsd_decimal([PLF],[PLF]) :- sva_plf_t_xsd_decimal(PLF). sva_content_t_xsd_integer([PLF],[PLF]) :- sva_plf_t_xsd_integer(PLF). sva_content_t_xsd_date([PLF],[PLF]) :- sva_plf_t_xsd_date(PLF).
sva_content_t_SKU([PLF],[PLF]) :- sva_plf_t_SKU(PLF). sva_content_t_e_quantity_t_e_item_t_Items([PLF],[PLF]) :- sva_plf_t_e_quantity_t_e_item_t_Items(PLF).
/* In our representation of XML, character data is * represented as atoms. Handling of non-ASCII characters is * OK if they are in UTF8, but the SWI parser currently has * trouble with some named entity references to non-ASCII * characters */ sva_plf_t_xsd_string(LF) :- atom(LF).Continued in <sva_plf rules for built-in types 10>, <Checking decimal and integer values 47>, <Checking date values 49>, <Checking date values 56>, <Checking date values 57>
sva_plf_t_xsd_decimal(PLF) :- ws_normalize(collapse,PLF,LF), atom_chars(LF,L), lexform_decimal(_,L,[]). sva_plf_t_xsd_integer(PLF) :- ws_normalize(collapse,PLF,LF), atom_chars(LF,L), lexform_integer(_,L,[]).
lexform_decimal ::= lexform_integer, fractionalpart.
lexform_integer ::= opt_sign, digits.
fractionalpart ::= [].
fractionalpart ::= decimalpoint.
fractionalpart ::= decimalpoint, opt_digits.
opt_sign ::= [].
opt_sign ::= ['+'].
opt_sign ::= ['-'].
decimalpoint ::= ['.'].
opt_digits ::= [].
opt_digits ::= digits.
/* We supply a 'lexval' property on digits, for use in
* date checking */
digits ::= digit^^D
<:> lexval([Dv]) ::- D^^lexval(Dv).
digits ::= digit^^D1, digits^^Dd
<:> lexval([D1val|Ddval]) ::-
D1^^lexval(D1val),
Dd^^lexval(Ddval).
digit ::= [Ch], { char_type(Ch,digit) }
<:> lexval(Ch).
sva_plf_t_xsd_date(PLF) :- ws_normalize(collapse,PLF,LF), atom_chars(LF,Lc), lexform_date(_,Lc,[]).
lexform_date ::= year^^Y, hyphen, month^^M, hyphen, day^^D,
{ Y^^val(Yv), M^^val(Mv), D^^val(Dv), dateok(Yv,Mv,Dv) }.
Continued in <Lexical form for year 51>, <Lexical form for month 54>, <Lexical form for day of month 55>
/* Years must have at least four digits */
yearnum ::= digit^^D1, digit^^D2, digit^^D3, digits^^Dd
<:> val(Num) ::- D1^^lexval(Dv1),
D2^^lexval(Dv2),
D3^^lexval(Dv3),
Dd^^lexval(Dv4),
flatten([Dv1,Dv2,Dv3,Dv4],LF),
number_chars(Num,LF).
year ::= yearnum^^Y
<:> val(Num) ::- Y^^val(Num).
year ::= ['-'], yearnum^^Y
<:> val(Num) ::- Y^^val(N), Num is 0 - N.
hyphen ::= ['-'].
month ::= ['0'], ['1']. month ::= ['0'], ['2']. ... month ::= ['0'], ['9']. month ::= ['1'], ['0']. month ::= ['1'], ['1']. month ::= ['1'], ['2'].
month ::= ['0'], digit^^D
{ D^^lexval(Dv), number_chars(V,Dv), V > 0 }
<:> val(V).
month ::= ['1'], digit^^D
{ D^^lexval(Dv), number_chars(V,Dv), V < 3 }
<:> val(Val) ::- Val is 10 + V.
month ::= digit^^D1, digit^^D2,
{ D1^^lexval(Dv1),
D2^^lexval(Dv2),
number_chars(Num,[Dv1,Dv2]),
Num > 0,
Num < 13 }
<:> val(Num).
day ::= digit^^D1, digit^^D2,
{ D1^^lexval(Dv1),
D2^^lexval(Dv2),
number_chars(Num,[Dv1,Dv2]),
Num > 0,
Num < 32 }
<:> val(Num).
dateok(_Y,_M,D) :- D < 29. dateok(_Y,M,29) :- M =\= 2. dateok(_Y,M,30) :- M =\= 2. dateok(_Y,M,31) :- member(M,[1,3,5,7,8,10,12]). dateok(Y,2,29) :- (Y >= 0 -> Yx = Y ; Yx is Y + 1), /* adjust for BC */ 0 is Yx mod 4, Lc is Yx mod 100, L4c is Yx mod 400, leapyearcheck(Lc,L4c).
/* if C is nonzero, it's not a century year, * so it's a leapyear */ leapyearcheck(C,_Q) :- C =\= 0. /* If both numbers are 0, it's a quad-century year, * so it's a leapyear */ leapyearcheck(0,0).
sva_plf_t_SKU(PLF) :-
ws_normalize(preserve,PLF,LF),
atom_chars(LF,Charseq),
lexform_t_SKU(_Structure,Charseq,[]).
lexform_t_SKU ::= sku_decimal_part, hyphen, sku_alpha_part.
sku_decimal_part ::= digit, digit, digit.
sku_alpha_part ::= cap_a_z, cap_a_z.
cap_a_z ::= [Char], { char_type(Char,upper) }.
Continued in <Value-checking rules for quantities 59>sva_plf_t_e_quantity_t_e_item_t_Items(PLF) :- ws_normalize(collapse,PLF,LF), atom_chars(LF,Lchars), lexform_integer(_,Lchars,[]), number_chars(Num,Lchars), Num < 100.
/* write_psvi(ParsedNode): write top-level element. */
write_psvi(Pn) :-
XPSVI = 'http://www.w3.org/People/cmsmcq/ns/xpsvi',
nsbindings(Pn,[ns('##NONE',''),ns(xpsvi,XPSVI)],Nsbs),
Pn ^^ local_name(Gi),
Pn ^^ namespace_name(NS),
Pn ^^ attributes(LPa),
Pn ^^ namespace_attributes(LPna),
Pn ^^ children(LCh),
uname_qname_context(NS,Gi,Nsbs,QN),
write('<'),
write(QN),
psvi_atts(LPa,Nsbs),
write(' xmlns:xpsvi="'), write(XPSVI), write('"'), nl,
psvi_nsatts(LPna,Nsbs),
psvi_props(Pn,Nsbs),
psvi_attprops(LPa,Nsbs),
write('>'),
psvi_children(LCh,Nsbs),
write('</'),
write(QN),
write('>'),
nl.
Continued in <Calculating list of active namespace bindings 61>, <Generating a QName from a namespace name and local name, given a list of namespace bindings 62>, <Writing out attributes in PSVI 65>, <Writing out namespace attributes in PSVI 70>, <Writing out PSVI properties for element 71>, <Writing out PSVI properties for attributes 76>, <Writing out children in PSVI 81>/* nsbindings(Pn,Inherited,Total): true if Total is a list of * namespace bindings, those attached to Pn first, then * the inherited ones. */ nsbindings(Pn,Inherited,Nsbs) :- Pn ^^ namespace_attributes(LPna), nsbind(Inherited,LPna,Nsbs). nsbind(Bindings,[],Bindings). nsbind(Inherited,[Pna | LPna],[ns(Pre,NS) | Nsbs]) :- Pna ^^ prefix(Pre), Pna ^^ namespace(NS), nsbind(Inherited,LPna,Nsbs).Continued in <Finding one binding for a namespace 64>
/* uname_qname_context(NS,Localname,Nsbs,QName) */
uname_qname_context(NS,Localname,Nsbs,QName) :-
binding(Nsbs,NS,Prefix),
Prefix \= '##NONE',
Prefix \= '',
concat_atom([Prefix,':',Localname],QName).
uname_qname_context(NS,Localname,Nsbs,Localname) :-
binding(Nsbs,NS,'##NONE').
uname_qname_context(NS,Localname,Nsbs,Localname) :-
binding(Nsbs,NS,'').
/* emergency: spit out a Uname if you have to */
uname_qname_context(NS,Localname,Nsbs,Uname) :-
not(binding(Nsbs,NS,_Prefix)),
concat_atom(['{',NS,'}',Localname],Uname).
Continued in <QName generation for attributes 63>
/* Attributes use special rules. */
uname_attname_context('',Localname,_Nsbs,Localname).
uname_attname_context('##NONE',Localname,_Nsbs,Localname).
uname_attname_context(NS,Localname,Nsbs,Qname) :-
NS \= '',
NS \= '##NONE',
uname_qname_context(NS,Localname,Nsbs,Qname).
/* binding(Nsbs,NS,Prefix) : true iff Prefix is bound * to NS in Nsbs. */ binding(Nsbs,NS,Prefix) :- binding(Nsbs,NS,[],Prefix). /* binding/4: return the first binding found for the namespace */ /* If the head of the list of bindings is for our NS, and the * prefix is not occluded, then return the prefix. */ binding([ns(Prefix,NS) | _Nsbs],NS,Occluded,Prefix) :- not(member(Prefix,Occluded)). /* If the head of the list of bindings is for our NS, but the * prefix is occluded, then recur. */ binding([ns(BadPrefix,NS) | Nsbs],NS,Occluded,Prefix) :- member(BadPrefix,Occluded), binding(Nsbs,NS,Occluded,Prefix). /* If the head of the list of bindings is not for our NS, * then recur. */ binding([ns(Prefix0,NS0) | Nsbs],NS,Occluded,Prefix) :- NS0 \= NS, binding(Nsbs,NS,[Prefix0 | Occluded], Prefix).