<TEI.2> ... <text id="T"> <body> <div1 id="a" type="chapter">...</div1> <div1 id="b" type="chapter">...</div1> <div1 id="c" type="chapter">...</div1> </body> </text> </TEI.2>then in the simple case I can say that text T consists of three chapters, represented in turn by elements a, b, and c. That is:
abbreviation(.). expansion(.,@expan).ignores the problems, while
abbreviation(token(.)). expansion(token(.),@expan,here).attempts to convey the distinction by the pseudo-function token(), which means simply ‘viewed as a token’, and the magic keyword here, which simply means “in this context” (without, I fear, attempting to specify what it is about the context which matters).
abbreviation(.). if @expan then expansion(.,@expan). if (@cert and @expan) then certainty(expansion(.,@expan)),@cert) else if (@expan) then certainty(expansion(.,@expan)),'unremarkable') if (@resp and @expan) then responsible(expansion(.,@expan)),person_denoted_by(idref(@resp))) else if (@expan) then responsible(expansion(.,@expan)),unknown) if (@type) then abbreviation_type(.,@type) else abbreviation_type(.,'')
<xsl:template match="abbr"> <xsl:variable name="this"> <xsl:call-template name="make-elemid"/> </xsl:variable> <xsl:text>abbreviation(</xsl:text> <xsl:value-of select="$this"/> <xsl:text>).&nl;</xsl:text> <xsl:if test="@expan"> <xsl:text>expansion(</xsl:text> <xsl:value-of select="$this"/> <xsl:text>,'</xsl:text> <xsl:value-of select="@expan"/> <xsl:text>').&nl;</xsl:text> <xsl:text>responsible(expansion(</xsl:text> <xsl:value-of select="$this"/> <xsl:text>,'</xsl:text> <xsl:value-of select="@expan"/> <xsl:text>'),</xsl:text> <xsl:choose> <xsl:when test="@resp"> <xsl:text>'</xsl:text> <xsl:value-of select="@resp"/> <xsl:text>'</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>unknown</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>).</xsl:text> <xsl:text>&nl;</xsl:text> <xsl:text>certainty(expansion(</xsl:text> <xsl:value-of select="$this"/> <xsl:text>,'</xsl:text> <xsl:value-of select="@expan"/> <xsl:text>'),</xsl:text> <xsl:choose> <xsl:when test="@cert"> <xsl:text>'</xsl:text> <xsl:value-of select="@cert"/> <xsl:text>'</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>unknown</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>).</xsl:text> <xsl:text>&nl;</xsl:text> </xsl:if> <xsl:if test="@type"> <xsl:text>abbreviation_type(</xsl:text> <xsl:value-of select="$this"/> <xsl:text>,'</xsl:text> <xsl:value-of select="@type"/> <xsl:text>').&nl;</xsl:text> </xsl:if> </xsl:template>
(1) The address is Southmoor <abbr expan="road">Rd</abbr>. (2) The address is Southmoor <abbr expan="road" resp="LB">Rd</abbr>. (3) <abbr type="acronym">RSVP</abbr> (4) <abbr type="organization">SPQR</abbr> (5) <abbr type="brevigraph">&per;</abbr> (6) <abbr type="contraction">yr hbl servt</abbr> (7) <abbr type="oganization" expan="senatus populusque romanorum" resp="author">SPQR</abbr>We get the following sentences (sorted):
abbreviation(n13). abbreviation(n15). abbreviation(n17). abbreviation(n19). abbreviation(n21). abbreviation(n23). abbreviation(n25). abbreviation_type(n17,'acronym'). abbreviation_type(n19,'organization'). abbreviation_type(n21,'brevigraph'). abbreviation_type(n23,'contraction'). abbreviation_type(n25,'oganization'). certainty(expansion(n13,'road'),unknown). certainty(expansion(n15,'road'),unknown). certainty(expansion(n25,'senatus populusque romanorum'),unknown). expansion(n13,'road'). expansion(n15,'road'). expansion(n25,'senatus populusque romanorum'). responsible(expansion(n13,'road'),unknown). responsible(expansion(n15,'road'),'LB'). responsible(expansion(n25,'senatus populusque romanorum'),'author').
historical_document(d1). xml_document(x1). encodes(x1,d1). /* or should this be encodes(n1,d1)? */ top_element(x1,n1). sender(d1,'Abraham Lincoln'). addressee(d1,'Richard Yates'). addressee(d1,'William Butler'). date(d1,'1862-04-10'). preparedBy(x1,'David R. Chesnutt and C. M. Sperberg-McQueen'). prepDate(x1,'31 August 1999'). prepDate(x1,'29 October 1999'). exemplar(x1,'Abraham Lincoln, Speeches and Writings 1859-1865 (New York: Library of America, 1989), p. 315'). place(d1,'Washington'). person('Richard Yates'). person('William Butler'). contains(d1,[o63,o72]). obj_class(o63,address). obj_class(o72,paragraph). encodes(n63,o63). encodes(n72,o72). ...
node(n61). gi(n61,docBody). travord(n61,61). nsib(n60,n61). parent(n61,n1). node(n62). gi(n62,'#pcdata'). travord(n62,62). first_child(n61,n62). parent(n62,n61). content(n62,"\n "). node(n63). gi(n63,address). travord(n63,63). nsib(n62,n63). parent(n63,n61). attv(n63,TEIform,'address'). node(n64). gi(n64,'#pcdata'). travord(n64,64). first_child(n63,n64). parent(n64,n63). content(n64,"\n "). node(n65). gi(n65,addrLine). travord(n65,65). nsib(n64,n65). parent(n65,n63). attv(n65,TEIform,'addrLine'). node(n66). gi(n66,'#pcdata'). travord(n66,66). first_child(n65,n66). parent(n66,n65). content(n66,"Hon. R. Yates & Wm. Butler"). node(n67). gi(n67,'#pcdata'). travord(n67,67). nsib(n65,n67). parent(n67,n63). content(n67,"\n "). node(n68). gi(n68,addrLine). travord(n68,68). nsib(n67,n68). parent(n68,n63). attv(n68,TEIform,'addrLine'). node(n69). gi(n69,'#pcdata'). travord(n69,69). first_child(n68,n69). parent(n69,n68). content(n69,"Springfield, Ills."). node(n70). gi(n70,'#pcdata'). travord(n70,70). nsib(n68,n70). parent(n70,n63). content(n70,"\n "). node(n71). gi(n71,'#pcdata'). travord(n71,71). nsib(n63,n71). parent(n71,n61). content(n71,"\n "). node(n72). gi(n72,p). travord(n72,72). nsib(n71,n72). parent(n72,n61). attv(n72,TEIform,'p'). node(n73). gi(n73,'#pcdata'). travord(n73,73). first_child(n72,n73). parent(n73,n72). content(n73,"I fully appreciate Gen. Pope's ... as blackberries."). node(n74). gi(n74,'#pcdata'). travord(n74,74). nsib(n72,n74). parent(n74,n61). content(n74,"\n"). node(n75). gi(n75,'#pcdata'). travord(n75,75). nsib(n61,n75). parent(n75,n1). content(n75,"\n").
has_property(n61,'document body'). constituent_part_of(n61,n1). has_property(n63,'address'). /* it's an address */ has_property(n63,'address of letter'). /* it's THE address */ constituent_part_of(n63,n61). has_property(n63, stringvalue("Hon. R. Yates & Wm. Butler / Springfield, Ills.")). /* is this a useful way to do string values? */ has_property(n65,'address line'). constituent_part_of(n65,n63). has_property(n65,stringvalue("Hon. R. Yates & Wm. Butler")). has_property(n68,'address line'). constituent_part_of(n68,n63). has_property(n68,stringvalue("Springfield, Ills.")). has_property(n72,'paragraph'). constituent_part_of(n72,n61). has_property(n72, stringvalue("I fully appreciate Gen. Pope's ... as blackberries.")).
person(yates,"Richard Yates"). person(butler,"William Butler"). person(lincoln,"Abraham Lincoln"). letter(al_to_yates_18620410,lincoln,[yates, butler]). transcript(al_to_yates_18620410,x1).Surely there is more to this?
<!DOCTYPE minutes SYSTEM "minutes.dtd" > <minutes lang="en"> <revisionHistory> <rev> <date>2002-03-21</date> <person>Paul</person> <what>drafted minutes during meeting</what> </rev> <rev> <date isoform="2002-03-31">31 Mar</date> <person>Paul</person> <what>put draft minutes on server</what> </rev> <rev> <date isoform="2002-03-21" lang="la">idem</date> <person>Paul</person> <what>found and fixed three typos, supply isoform attributes for some dates, put fresh copy on server</what> </rev> </revisionHistory> <present> <person>John</person> <person>Paul</person> </present> <absent> <person>Pius</person> </absent> <date isoform="2002-03-21">21 March 2002</date> <body> <p><person>John</person> expressed concern about <person>Pius</person>'s attendance record. <resolved>to increase the fine for missed meetings to a nickel.</resolved></p> <p>We discussed the date and place of the next meeting.</p> <p>Agreed: <b>Next meeting is <date>28 March</date>, usual place</b>. <action> <person>Paul</person> <what>to order refreshments</what> <when>26 March</when> </action> (N.B. The kitchen is, <i lang="la">mirabile dictu</i>, demanding two days' notice for refreshments now.)</p> </body> </minutes>
<!ENTITY % phrases "(#PCDATA |date | i | b | person | action | resolved)*" > <!ENTITY % a.global "lang NMTOKEN #IMPLIED"> <!ELEMENT minutes (revisionHistory?, present, absent, date, body) > <!ATTLIST minutes %a.global; > <!ELEMENT revisionHistory (rev*) > <!ATTLIST revisionHistory %a.global; > <!ELEMENT rev (date, person, what) > <!ATTLIST rev %a.global; > <!ELEMENT present (person*) > <!ATTLIST present %a.global; > <!ELEMENT absent (person*) > <!ATTLIST absent %a.global; > <!ELEMENT person (#PCDATA) > <!ATTLIST person %a.global; > <!ELEMENT date (#PCDATA) > <!ATTLIST date %a.global; isoform CDATA #IMPLIED> <!ELEMENT body (p | action | resolved | div)* > <!ATTLIST body %a.global; > <!ELEMENT div (head, (p | action | resolved | div)*) > <!ATTLIST div %a.global; > <!ELEMENT action (person, what, when) > <!ATTLIST action %a.global; > <!ELEMENT resolved %phrases; > <!ATTLIST resolved %a.global; > <!ELEMENT what (#PCDATA) > <!ATTLIST what %a.global; > <!ELEMENT when (#PCDATA |date)* > <!ATTLIST when %a.global; > <!ELEMENT head (#PCDATA | date | i | b | person)* > <!ATTLIST head %a.global; <!ELEMENT p %phrases; > <!ATTLIST p %a.global; > <!ELEMENT i %phrases; > <!ATTLIST i %a.global; > <!ELEMENT b %phrases; > <!ATTLIST b %a.global; >
node(n1). node(n2). ... node(n99). travord(n1,1). ... travord(n99,99).
gi(n01,minutes). gi(n02,'#pcdata'). gi(n03,revisionHistory). gi(n04,'#pcdata'). gi(n05,rev). gi(n07,date). gi(n10,person). gi(n13,what). gi(n17,rev). gi(n19,date). gi(n22,person). gi(n25,what). gi(n29,rev). gi(n31,date). gi(n34,person). gi(n37,what). gi(n42,present). gi(n44,person). gi(n47,person). gi(n51,absent). gi(n53,person). gi(n57,date). gi(n60,body). gi(n62,p). gi(n63,person). gi(n66,person). gi(n69,resolved). gi(n72,p). gi(n75,p). gi(n77,b). gi(n79,date). gi(n83,action). gi(n85,person). gi(n88,what). gi(n91,when). gi(n95,i).(N.B. the SWI parser omits some of these nodes: being an SGML parser at heart, it cannot bring itself to report text nodes for white space in element content. My XML parser is less merciful.)
attv(n01,lang,'en'). attv(n19,isoform,'2002-03-31'). attv(n31,isoform,'2002-03-21'). attv(n31,lang,'la'). attv(n57,isoform,'2002-03-21'). attv(n95,lang,'la').
content(n02,"\n"). content(n04,"\n"). content(n08,"2002-03-21"). content(n11,"Paul"). content(n14,"drafted minutes during meeting"). content(n20,"31 Mar"). content(n23,"Paul"). content(n26,"put draft minutes on server"). content(n32,"idem"). content(n35,"Paul"). content(n38,"found and fixed three typos, supply\nisoform attributes for some dates, put fresh copy on server"). content(n45,"John"). content(n48,"Paul"). content(n54,"Pius"). content(n58,"21 March 2002"). content(n64,"John"). content(n65," expressed concern about "). content(n67,"Pius"). content(n68,"'s\nattendance record.\n"). content(n70,"to increase the fine for missed meetings to a nickel."). content(n73,"We discussed the date and place of the next meeting."). content(n76,"Agreed: "). content(n78,"Next meeting is "). content(n80,"28 March"). content(n81,", usual place"). content(n82,".\n"). content(n86,"Paul"). content(n89,"to order refreshments"). content(n92,"26 March"). content(n94,"\n(N.B. The kitchen is, "). content(n96,"mirabile dictu"). content(n97,",\ndemanding two days' notice for refreshments now.)").
first_child(n01,n02). first_child(n03,n04). first_child(n05,n06). first_child(n07,n08). first_child(n10,n11). first_child(n13,n14). first_child(n17,n18). first_child(n19,n20). ... nsib(n02,n03). nsib(n03,n41). nsib(n04,n05). nsib(n05,n16). nsib(n06,n07). nsib(n07,n09). nsib(n09,n10). nsib(n10,n12). nsib(n12,n13). nsib(n13,n15). nsib(n16,n17). nsib(n17,n28). nsib(n18,n19). nsib(n19,n21). ... parent(n02,n01). parent(n03,n01). parent(n04,n03). parent(n05,n03). parent(n06,n05). parent(n07,n05). parent(n08,n07). parent(n09,n05). ... parent(n99,n01).
minutes(n01).
revision_list(n03). present_list(n42). absent_list(n51). minutes_body(n60). date(n57).
date(n07). date(n19). date(n31). person_name(n10). person_name(n22). person_name(n34). what(n13). what(n25). what(n37). revision_event(n05). revision_event(n17). revision_event(n29).and in the lists of those present and absent:
person_name(n44). person_name(n47). person_name(n53).
p(n62). p(n72). p(n75).and action items and resolutions (together with their contents):
resolution(n69). action_item(n83). person_name(n85). what(n88). when(n91).And floating around in the prose soup, we have some remaining stuff:
person_name(n63). person_name(n66). date(n79). bold_phrase(n77). italic_phrase(n95).We note in passing that the words
Agreed: <b>Next meeting is <date>28 March</date>, usual place</b>.ought perhaps to have been captured as a resolved element. A human might well treat it in much the same way, unless aware that the organization in question had decided to distinguish scheduling decisions from other resolutions. A machine working only from the markup has no choice but to distinguish the two. The inferences will only be as good as the markup: garbage in, garbage out, and no silk purses will be made out of sows' ears.
part_whole(n05,n03). /* rev is part of revisionHistory */ part_whole(n07,n05). /* date is part of rev */ part_whole(n10,n05). /* person is part of rev */ part_whole(n13,n05). /* what is part of rev */ part_whole(n17,n03). /* rev is part of revisionHistory */ part_whole(n19,n17). /* date is part of rev */ part_whole(n22,n17). /* person is part of rev */ part_whole(n25,n17). /* what is part of rev */ part_whole(n29,n03). /* rev is part of revisionHistory */ part_whole(n31,n29). /* date is part of rev */ part_whole(n34,n29). /* person is part of rev */ part_whole(n37,n29). /* what is part of rev */ part_whole(n42,n01). /* present is part of minutes */ part_whole(n51,n01). /* absent is part of minutes */ part_whole(n57,n01). /* date is part of minutes */ part_whole(n60,n01). /* body is part of minutes */ part_whole(n44,n42). /* person is part of present */ part_whole(n47,n42). /* person is part of present */ part_whole(n53,n51). /* person is part of absent */ part_whole(n62,n60). /* p is part of body */ part_whole(n72,n60). /* p is part of body */ part_whole(n75,n60). /* p is part of body */ part_whole(n85,n83). /* person is part of action */ part_whole(n88,n83). /* what is part of action */ part_whole(n91,n83). /* when is part of action */
/* successor predicate: direct adjacency */ succ(n05,n17). /* the rev elements are ordered */ succ(n17,n29). succ(n62,n72). /* the p elements within the body are ordered */ succ(n72,n75). succ(n63,n65). /* the contents of each p element are ordered */ succ(n65,n66). succ(n66,n68). succ(n68,n69). /* paragraph n72 has only one child, no sequencing applies */ succ(n76, n77). succ(n77, n82). succ(n82, n83). succ(n83, n94). succ(n94, n95). succ(n95, n97).Note that the children of minutes (present, absent, date, and body) are not ordered by the succ predicate. The DTD prescribes the order, so the order of appearance does not convey any information not already conveyed by the minutess tag. If the DTD did allow multiple orders, we could specify that order is not significant by formulating a rule which ensures that no succ relation holds between siblings.
precedes(X,Y) :- succ(X,Y). precedes(X,Y) :- succ(X,Z), precedes(Z,Y). precedes(X,Y) :- parent(X,Z), precedes(Z,Y). precedes(X,Y) :- parent(Y,Z), precedes(X,Z).(I suspect this may allocate sequential position to some things I'd rather not see sequenced, but I'll let it go for now.)
lang(n14,"en"). /* "drafted minutes during meeting" */ lang(n20,"en"). /* "31 Mar" */ lang(n26,"en"). /* "put draft minutes on server" */ lang(n38,"en"). /* "found and fixed three typos, ..." */ lang(n58,"en"). /* "21 March 2002" */ lang(n65,"en"). /* " expressed concern about " */ lang(n68,"en"). /* "'s\nattendance record.\n" */ lang(n70,"en"). /* "to increase the fine for missed meetings to a nickel." */ lang(n73,"en"). /* "We discussed the date and place of the next meeting." */ lang(n76,"en"). /* "Agreed: " */ lang(n78,"en"). /* "Next meeting is " */ lang(n80,"en"). /* "28 March" */ lang(n81,"en"). /* ", usual place" */ lang(n89,"en"). /* "to order refreshments" */ lang(n92,"en"). /* "26 March" */ lang(n94,"en"). /* "\n(N.B. The kitchen is, " */ lang(n97,"en"). /* ",\ndemanding two days' notice for refreshments now.)" */Note that “31 Mar”, at least, could also be encountered without surprise in some other languages. The claim that it's in English is a claim about the occurrence of “31 Mar” here, not other possible occurrences. That is, the lang predicate applies to the tokens (or to the specific text node), not to the string.
lang(n32,"la"). /* "idem" */ lang(n96,"la"). /* "mirabile dictu" */
lang(n08,"und"). /* "2002-03-21" */ lang(n11,"und"). /* "Paul" */ lang(n23,"und"). /* "Paul" */ lang(n35,"und"). /* "Paul" */ lang(n45,"und"). /* "John" */ lang(n48,"und"). /* "Paul" */ lang(n54,"und"). /* "Pius" */ lang(n64,"und"). /* "John" */ lang(n67,"und"). /* "Pius" */ lang(n86,"und"). /* "Paul" */The challenge for us is finding a way to prevent the language property from propagating into the elements dominating these text nodes.
lang(n13,"en"). /* what */ lang(n19,"en"). /* date */ lang(n25,"en"). /* what */ lang(n37,"en"). /* what */ lang(n57,"en"). /* date */ lang(n69,"en"). /* resolved */ lang(n72,"en"). /* p */ lang(n77,"en"). /* b */ lang(n79,"en"). /* date */ lang(n88,"en"). /* what */ lang(n91,"en"). /* when */ lang(n31,"la"). /* date */ lang(n95,"la"). /* i */ lang(n07,"und"). /* date */ lang(n10,"und"). /* person */ lang(n22,"und"). /* person */ lang(n34,"und"). /* person */ lang(n42,"und"). /* present */ lang(n44,"und"). /* person */ lang(n47,"und"). /* person */ lang(n51,"und"). /* absent */ lang(n53,"und"). /* person */ lang(n63,"und"). /* person */ lang(n66,"und"). /* person */ lang(n85,"und"). /* person */
lang(n01,"mul"). /* minutes */ lang(n03,"mul"). /* revisionHistory */ lang(n05,"mul"). /* rev */ lang(n17,"mul"). /* rev */ lang(n29,"mul"). /* rev */ lang(n60,"mul"). /* body */ lang(n62,"mul"). /* p */ lang(n75,"mul"). /* p */ lang(n83,"mul"). /* action */And if we specified that when undetermined language and a specified language mix, then the parent should be tagged with the specified language, some elements will change their tagging:
lang(n05,"en"). /* rev */ lang(n17,"en"). /* rev */ lang(n62,"en"). /* p */ lang(n83,"en"). /* action */
?- part_whole(n42,n01). Yes ?-We can also ask what items it's true for:
49 ?- part_whole(X,Y). X = n05 Y = n03 ; X = n07 Y = n05 Yes(For the Prolog novices among us, I should observe that the lines beginning with X and Y were typed by the system, but the semicolons ending some of them were typed by the user. The semicolon is used in Prolog as an 'or' connector, and responding to a solution of a goal with ';' is a way of asking to see other solutions. After the last one, the system replies 'Yes' because it succeeded in finding a solution the last time I asked; if I had continued to press ';', eventually there would be no further solutions and the final answer would be No.)
minutes(X) :- node(X), gi(X,minutes).In the current state of play, the node(X) is redundant because nothing that is not a node appears as the first argument of a gi/2 predicate.
present_list(X) :- node(X), gi(X,present). absent_list(X) :- node(X), gi(X,absent).We will want, eventually, to stipulate that a particular list of people present belongs to a particular set of minutes, but for now CH and MSM are guessing that this belongs in the application-sentence layer, not here.
date(X) :- node(X), gi(X,date). standard_value_of_date(X,Y) :- date(X), attv(X,isoform,Y).Alternatively, we could decide that we wish to distinguish the usages at the property level, possibly on the grounds that the differentiae relate to document structure. In which case we...
nearest_lang(N,L) :- node(N), gi(N,'#pcdata'), nearest_anc(N,'lang',L,_). lingual(N) :- node(N), gi(N,'#pcdata'), not(ancestor(N,A), gi(A,G), non_lingual(G)). lang(N,L) :- lingual(N), nearest_lang(N,L). lang(N,"und") :- not(lingual(N)).For elements (perhaps the complexity here is such that we ought not to assign the property to elements? but then what do we do when we encounter a vocabulary whose designer says explicitly that elements do have such and such a bottom-up property?), we might have:
/* We define child_language(N,L) as a relation holding between a parent node and the languages of its child nodes. Then setof(L,child_language(N,L), List) returns a List of all the languages of all the children. */ child_language(N,L) :- parent(C,N), lang(C,L). lang(N,"qqq") :- setof(L,child_language(N,L),[]). lang(N,L) :- setof(L,child_language(N,L),[L]). lang(N,"mul") :- setof(L,child_language(N,L),[H|T]).I have added an explicit code (qqq) for material without a meaninful lang property value; in the description above, no assertions were made about these nodes, but it seems easier in the Prolog to assert something for every node. The code qqq is from a range “Reserved for local use”.
16 ?- dynamic(part_whole/2). Yes 17 ?- findall(part_whole(P,W), part_whole(P,W), Bag), asserta_each(Bag). P = _G555 W = _G556 Bag = [part_whole(n05, n03), part_whole(n07, n05), part_whole(n10, n05), part_w\ hole(n13, n05), part_whole(n17, n03), part_whole(n19, n17), part_whole(n22, n17\ ), part_whole(n25, n17), part_whole(..., ...)|...] Yes 18 ?-where asserta_each is defined this way:
asserta_each([]). asserta_each([H|T]) :- asserta(H), asserta_each(T).Analogous clauses for assert, assertz, record, recorda, recordz, etc. could be used.
meeting(m234). meeting_date(m234,'2002-03-21'). meeting_minutes(m234,n01). person(p1,"John"). person(p2,"Paul"). person(p3,"Pius"). meeting_attendees(m234,[p1,p2]). meeting_absentees(m234,[p3]). resolution(r33,"to increase the fine for missed meetings to a nickel."). action(a347,p2,informal-date("26 March"),"to order refreshments"). meeting_resolutions(m234,[r33]). meeting_actions(m234,[a347]).
class(document). /* ? minutes will be of type document */ class(minutes). subclass(minutes,document). class(meeting).
object(o1). obj_class(doc33,minutes). object(o2). obj_class(o2,meeting).We don't say (here) that it was from the existence of the minutes (o1) that we inferred the existence of the meeting (o2), but that's OK. That's the role of the mapping axioms.[5]
property_of(meeting,date,string). opv(o2,date,"2002-03-21").This, however, won't do justice to dates, which have (in the sample DTD) both a string form (the content of the date element) and a normalized ISO-format form, the latter being optional. We might describe dates this way: [6]
class(date). property_of(date,localform,string). property_of(date,isoform,string).Thus armed, we can make our application sentences better:
property_of(meeting,date,object(date)). object(o3). obj_class(o3,date). opv(o2,date,o3). opv(o3,localform,"2002-03-21").In reality, someone will observe that “2002-03-21” is itself in ISO form, and so we will also have the inference
opv(o3,localform,"2002-03-21").but I don't think that's markup-based inference. It's based on knowledge of real-world date formats. (Unless of course the DTD had the rule “The isoform attribute may be omitted if and only if the content is already in ISO form. But it's doubtful that Paul, who seems to have done the DTD, did it that way.)”
property_of(meeting,minutes,object(minutes)). opv(o2,minutes,o3).
class(person). property_of(person,name,string). object(o4). obj_class(o4,person). opv(o4,name,"John"). object(o5). obj_class(o5,person). opv(o4,name,"Paul"). object(o6). obj_class(o6,person). opv(o4,name,"Pius"). relation(person_attends_meeting,[person, meeting]). relation(person_misses_meeting,[person, meeting]). relation_applies(person_attends_meeting,o4,o2). relation_applies(person_attends_meeting,o5,o2). relation_applies(person_misses_meeting,o6,o2).
class(resolution). class(action). property_of(resolution, meeting, object(meeting)). property_of(resolution, text, string). property_of(action, meeting, object(meeting)). property_of(action, who, string). property_of(action, when, string). property_of(action, what, string).The content model for the when element is (#PCDATA | date)*, which is (we can hypothesize) intended to accommodate instantiations like <when>Whenever it's convenient, but no later than <date>next Thursday</date></when>. The property defined above is thus a bit too simple: the when property is not a string, but a string which may contain date objects. A full working out of an object class informal-date might be rewarding, but I'll pass for now, and simply say that in addition to the properties defined above, actions can have a relation to date objects; the DTD ensures that date elements can occur only in the when element.
relation(action_duedate,[action,date]).
relation(meeting_makes_resolution,[meeting,resolution]). relation(meeting_assigns_action,[meeting,action]).
object(o7). obj_class(o7,resolution). opv(o7,text,"to increase the fine for missed meetings to a nickel."). opv(o7,meeting,o2). relation_applies(meeting_makes_resolution(o2,o7). object(o8). obj_class(o8,action). opv(o8,who,"Paul"). opv(o8,when,"to order refreshments"). opv(o8,what,"26 March"). opv(o8,meeting,o2). relation_applies(meeting_assigns_action(o2,o8). object(o9). obj_class(o9,date). opv(o9,localform,"26 March"). relation_applies(action_duedate(o8,o9).
lang="X" → child::text() has language X & child::*[not(@lang)] has language XNote that the notion “element E has language L” ought to mean about the same thing as “element E has the attribute-value specification lang="X"”, but this formulation doesn't quite get there.
(for all x) (gi(x,'#pcdata') → haslang(x,ancestor::*[@lang][1]/@lang))or, roughly, “for all x, if x is a text node, then the haslang property of x has the value of the lang attribute on the nearest ancestore which has a lang attribute.” [12]
(1) attv(N,lang,L) → haslang(N,L). (2) haslang(N,L) → (for all y)(parent(y,N) & ¬(attv(y,lang,_)) → haslang(y,L)) & (for all y)(parent(y,N) & gi(y,'#pcdata') → haslang(y,L))where the meaning of haslang(N,L) is approximately “if N is a text node, the tokens in N are in language L; if N is an element node, the text nodes in N are in language L unless otherwise specified.” I think this captures the meaning reasonably well, but in practical terms I am uneasy for reasons I cannot quite identify. I think I am uneasy because relying on sentence (2) for the core notion of distribution means I don't know how to make XSLT or Prolog generate the base set of inferences.
(for all x : element) (attv(x,lang,_) → language(x,x->@lang)) (for all x : element) (¬attv(x,lang,_) → language(x,x->ancestor::*[@lang][1]/@lang)).The notation e->E may be read as “the value of the Xpath expression E interpreted with node e as the current node”.
(for all x : node) ((element(x) | attribute(x) | textnode(x)) → language(x,x->ancestor-or-self::*[@lang][1]/@lang))
Ae[element(e) → hasprop(.,language(ancestor-or-self::*[@lang][1]/@lang))] Aa[[att(a) | text(a)] & hasprop(parent::*,language(L)) → hasprop(.,language(L))]
let L = ancestor-or-self::*[@lang][1]/@lang) in (hasprop(.,language(L)) & hasprop(child::text(),language(L)) & hasprop(attribute::*,language(L)) )
Ey[Ax[mayor'(x) ↔ x = y] ^ walk'(y)]was that we can handle this problem more easily than I had feared. I think we can handle bibl and title by saying in the rule for bibl something like
Ex[bibliographic_item(x) & bibl_describes_item(.,x) & Ay[bibl_describes_item(y) ↔ x = y]]and then in the rule for title something like
title(.) & Ax[bibl_describes_item(ancestor::bibl, x) → title_of_item(.,x)]
minutes(n1). present_list(n1,n3). /* n3 is the present list OF n1! */ absent_list(n1,n4).At the moment, CH and MSM propose to postpone the association of n3 with n1 to the application sentences.
person_name("John"). person_name("Paul").etc., if we took the predicate to be a statement about the type, rather than the token.
whole_part_kind(n1,[n3,n4,n18,n21],tuple). whole_part_kind(n21,[n23,n33,n36],sequence).where the keywords tuple and sequence record whether predicates like precedes(X,Y) are applicable on this level or not. The keyword set would also be in order, but there might be no practical difference between tuple and set in that case.
unordered(n03). unordered(n42). unordered(n51). unordered(n57). unordered(n60).meaning that the nodes indicated are not ordered with respect to their siblings.