So, I've been messing around with vcards a bit and decided that I would try to make sense of the new XML format for VCARD data, described here:
http://tools.ietf.org/html/draft-perreault-vcarddav-vcardxml-02#appendix-A
So far so good. I cut and paste the RNG spec from the document (attached), and attempt to read in the compact form and write out the longhand XML RNG schema. So, I do:
(defparameter *compact* (cxml-rng:parse-compact #p"vcard-4_0.rng")) ;; so far so good
(cxml-rng:make-validator *compact*) ;; again, that works
(with-open-file (out "foo.xml" :direction :output :element-type '(unsigned-byte 8)) (cxml-rng:serialize-schema *compact* (cxml:make-octet-stream-sink out))) ;; BOOM!
I get the following error:
There is no applicable method for the generic function #<STANDARD-GENERIC-FUNCTION CXML:UNPARSE-ATTRIBUTE (3)> when called with arguments (#:ANONYMOUS2507). [Condition of type SIMPLE-ERROR]
Restarts: 0: [RETRY] Retry calling the generic function. 1: [*ABORT] Return to SLIME's top level. 2: [TERMINATE-THREAD] Terminate this thread (#<THREAD "worker" RUNNING {1002D97001}>)
Backtrace: 0: ((SB-PCL::FAST-METHOD NO-APPLICABLE-METHOD (T)) #<unused argument> #<unused argument> #<STANDARD-GENERIC-FUNCTION CXML:UNPARSE-ATTRIBUTE (3)> #:ANONYMOUS2507) 1: (SB-PCL::CALL-NO-APPLICABLE-METHOD #<STANDARD-GENERIC-FUNCTION CXML:UNPARSE-ATTRIBUTE (3)> (#:ANONYMOUS2507)) 2: (CXML:ATTRIBUTE* #<unavailable argument> #<unavailable argument> #<unavailable argument> "name") Locals: CXML::LNAME = :<NOT-AVAILABLE> CXML::PREFIX = :<NOT-AVAILABLE> CXML::QNAME = "name" CXML::VALUE = :<NOT-AVAILABLE> 3: ((LAMBDA ())) 4: (CXML::INVOKE-WITH-ELEMENT* #<CLOSURE (LAMBDA #) {1002E13BA9}> #<unavailable argument> #<unavailable argument> "ref") Locals: CXML::FN = #<CLOSURE (LAMBDA ()) {1002E13BA9}> CXML::LNAME = :<NOT-AVAILABLE> CXML::PREFIX = :<NOT-AVAILABLE> CXML::QNAME = "ref" 5: (CXML-RNG::SERIALIZE-PATTERN #<CXML-RNG:REF {1006DB5171}>) 6: ((LAMBDA ())) 7: (CXML::INVOKE-WITH-ELEMENT* #<CLOSURE (LAMBDA #) {1002E13AF9}> #<unavailable argument> #<unavailable argument> "start") Locals: CXML::FN = #<CLOSURE (LAMBDA ()) {1002E13AF9}> CXML::LNAME = :<NOT-AVAILABLE> CXML::PREFIX = :<NOT-AVAILABLE> CXML::QNAME = "start" 8: ((LAMBDA ())) 9: (CXML::INVOKE-WITH-ELEMENT* #<CLOSURE (LAMBDA #) {1002E13A89}> #<unavailable argument> #<unavailable argument> "grammar")
Now, normally, I'd just assume that this is something I messed up. But the fact that the schema parses and validates OK makes me wonder. Any suggestions on how to go about debugging this?
thanks,
Cyrus
Forgot the schema:
default namespace = "urn:ietf:params:xml:ns:vcard-4.0"
# Value types \text = element text { text } text-list = \text+ uri = element uri { xsd:anyURI } date = element date { xsd:string { pattern = "\d{8}|\d{4}-\d\d|--\d\d(\d\d)?|---\d\d" } } time = element time { xsd:string { pattern = "(\d\d(\d\d(\d\d)?)?|-\d\d(\d\d?)|--\d\d)" ~ "(Z|[+-]\d\d(\d\d)?)?" } } date-time = element date-time { xsd:string { pattern = "(\d{8}|--\d{4}|---\d\d)T\d\d(\d\d(\d\d)?)?" ~ "(Z|[+-]\d\d(\d\d)?)?" } } date-and-or-time = date | date-time | time timestamp = element timestamp { xsd:string { pattern = "\d{8}T\d{6}(Z|[+-]\d\d(\d\d)?)?" } } boolean = element boolean { xsd:boolean } integer = element integer { xsd:integer } float = element float { xsd:float } binary = element binary { xsd:base64Binary } language-tag = element language-tag { xsd:string { pattern = "([a-z]{2,3}((-[a-z]{3}){0,3})?|[a-z]{4,8})" ~ "(-[a-z]{4})?(-([a-z]{2}|\d{3}))?" ~ "(-([0-9a-z]{5,8}|\d[0-9a-z]{3}))*" ~ "(-[0-9a-wyz](-[0-9a-z]{2,8})+)*(-x(-[0-9a-z]{1,8})+)?|" ~ "x(-[0-9a-z]{1,8})+|[a-z]{1,3}(-[0-9a-z]{2,8}){1,2}" } } data = (element type { xsd:string { pattern = "[A-Za-z\d!#$&.+-^_]{1,127}/" ~ "[A-Za-z\d!#$&.+-^_]{1,127}" } }, binary) | uri
# Parameters language = element language { language-tag }? pref = element pref { xsd:integer { minInclusive = "1" maxInclusive = "100" } }? pid = element pid { xsd:string { pattern = "\d+(.\d+)?" } }?
# Properties source = element source { pid, pref, uri } name = element name { \text } kind = element kind { element individual { empty } | element group { empty } | element org { empty } | element location { empty } } fn = element fn { language, pid, pref, \text } n = element n { language, element surname { text-list }, element given { text-list },
element prefix { text-list }, element suffix { text-list } } nickname = element nickname { language, pid, pref, text-list } photo = element photo { pid, pref, data } bday = element bday { date-and-or-time | \text } dday = element dday { date-and-or-time | \text } birth = element birth { language, \text } death = element death { language, \text } anniversary = element anniversary { date-and-or-time | \text } sex = element sex { "0" | "1" | "2" | "9" } adr = element adr { language, element geo { uri }?, element tz { \text | uri }?, pid, pref, element pobox { text-list }, element ext { text-list }, element street { text-list }, element locality { text-list }, element region { text-list }, element code { text-list }, element country { text-list } } label = element label { language, pid, pref, \text } tel = element tel { element type { element text { empty }?, element voice { empty }?, element fax { empty }?, element cell { empty }?, element video { empty }?, element pager { empty }? }?, pid, pref, uri } email = element email { pid, pref, \text } impp = element impp { pid, pref, uri } lang = element lang { pid, pref, language-tag } tz = element tz { pid, pref, (\text | uri) } geo = element geo { pid, pref, uri } title = element title { language, pid, pref, \text } role = element role { language, pid, pref, \text }
logo = element logo { language, pid, pref, data } org = element org { language, pid, pref, text-list } member = element member { pid, pref, uri } related = element related { element type { element parent { empty } | element child { empty } | element sibling { empty } | element spouse { empty } | element family { empty } | element friend { empty } | element supervisor { empty } | element supervisee { empty } | element assistant { empty } | element colleague { empty } | element agent { empty } | element emergency { empty } }?, pid, pref, (uri | \text) } categories = element categories { pid, pref, \text } note = element note { language, pid, pref, \text } prodid = element prodid { \text } rev = element rev { timestamp } sort-string = element sort-string { \text } sound = element sound { language, pid, pref, data } uid = element uid { uri } clientpidmap = element clientpidmap { element sourceid { xsd:positiveInteger }, uri } url = element url { pid, pref, uri } class = element class { element PUBLIC { empty } | element PRIVATE { empty } | element CONFIDENTIAL { empty } } key = element key { pid, pref, data } fburl = element fburl { pid, pref, uri } caladruri = element caladruri { pid, pref, uri } caluri = element caluri { pid, pref, uri }
# Top-level grammar group-property = fn | nickname | photo | adr | label | tel | email | impp | lang | tz | geo | title | role | logo | org | related | categories | note | sound | url | key | fburl | caladruri | caluri any-property = group-property | source | name | kind | n | bday | dday | birth | death | anniversary | sex | member | prodid | rev | sort-string | uid | clientpidmap | class start = element vcard { (any-property | element group { attribute name { text }, group-property* })* }
Well, David fixed the bug (in git HEAD) by making sure that the ref label is a string. But that leads to the next problem... Why are there so many refs when parsing this schema in the first place? When I try to serialize this back out, I get:
<?xml version="1.0" encoding="UTF-8"?> <grammar> <start> <ref name="ANONYMOUS3160"/> </start> <define name="ANONYMOUS3160"> <element> <name ns="urn:ietf:params:xml:ns:vcard-4.0"> vcard</name> <choice> <empty/> <oneOrMore> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <choice> <ref name="ANONYMOUS3084"/> <ref name="ANONYMOUS3090"/> </choice> <ref name="ANONYMOUS3091"/> </choice> <ref name="ANONYMOUS3107"/> </choice> <ref name="ANONYMOUS3108"/> </choice> <ref name="ANONYMOUS3116"/> </choice> <ref name="ANONYMOUS3117"/> </choice> <ref name="ANONYMOUS3118"/> </choice> <ref name="ANONYMOUS3119"/> </choice> <ref name="ANONYMOUS3120"/> </choice> <ref name="ANONYMOUS3121"/> </choice> <ref name="ANONYMOUS3122"/> </choice> <ref name="ANONYMOUS3123"/> </choice> <ref name="ANONYMOUS3124"/> </choice> <ref name="ANONYMOUS3125"/> </choice> <ref name="ANONYMOUS3140"/> </choice> <ref name="ANONYMOUS3141"/> </choice> <ref name="ANONYMOUS3142"/> </choice> <ref name="ANONYMOUS3146"/> </choice> <ref name="ANONYMOUS3150"/> </choice> <ref name="ANONYMOUS3155"/> </choice> <ref name="ANONYMOUS3156"/> </choice> <ref name="ANONYMOUS3157"/> </choice> <ref name="ANONYMOUS3158"/> </choice> <ref name="ANONYMOUS3077"/> </choice> <ref name="ANONYMOUS3078"/> </choice> <ref name="ANONYMOUS3083"/> </choice> <ref name="ANONYMOUS3089"/> </choice> <ref name="ANONYMOUS3092"/> </choice> <ref name="ANONYMOUS3093"/> </choice> <ref name="ANONYMOUS3094"/> </choice> <ref name="ANONYMOUS3095"/> </choice> <ref name="ANONYMOUS3096"/> </choice> <ref name="ANONYMOUS3097"/> </choice> <ref name="ANONYMOUS3126"/> </choice> <ref name="ANONYMOUS3143"/> </choice> <ref name="ANONYMOUS3144"/> </choice> <ref name="ANONYMOUS3145"/> </choice> <ref name="ANONYMOUS3147"/> </choice> <ref name="ANONYMOUS3149"/> </choice> <ref name="ANONYMOUS3154"/> </choice> <ref name="ANONYMOUS3159"/> </choice> </oneOrMore> </choice> </element> </define> ...
And all of these anonymous refs seem to only be used (well, many of them anyway). Couldn't they just be replaced with the definition?
thanks,
Cyrus
On Apr 27, 2011, at 11:07 PM, Cyrus Harmon wrote:
Forgot the schema:
default namespace = "urn:ietf:params:xml:ns:vcard-4.0"
# Value types \text = element text { text } text-list = \text+ uri = element uri { xsd:anyURI } date = element date { xsd:string { pattern = "\d{8}|\d{4}-\d\d|--\d\d(\d\d)?|---\d\d" } } time = element time { xsd:string { pattern = "(\d\d(\d\d(\d\d)?)?|-\d\d(\d\d?)|--\d\d)" ~ "(Z|[+-]\d\d(\d\d)?)?" } } date-time = element date-time { xsd:string { pattern = "(\d{8}|--\d{4}|---\d\d)T\d\d(\d\d(\d\d)?)?" ~ "(Z|[+-]\d\d(\d\d)?)?" } } date-and-or-time = date | date-time | time timestamp = element timestamp { xsd:string { pattern = "\d{8}T\d{6}(Z|[+-]\d\d(\d\d)?)?" } } boolean = element boolean { xsd:boolean } integer = element integer { xsd:integer } float = element float { xsd:float } binary = element binary { xsd:base64Binary } language-tag = element language-tag { xsd:string { pattern = "([a-z]{2,3}((-[a-z]{3}){0,3})?|[a-z]{4,8})" ~ "(-[a-z]{4})?(-([a-z]{2}|\d{3}))?" ~ "(-([0-9a-z]{5,8}|\d[0-9a-z]{3}))*" ~ "(-[0-9a-wyz](-[0-9a-z]{2,8})+)*(-x(-[0-9a-z]{1,8})+)?|" ~ "x(-[0-9a-z]{1,8})+|[a-z]{1,3}(-[0-9a-z]{2,8}){1,2}" } } data = (element type { xsd:string { pattern = "[A-Za-z\d!#$&.+-^_]{1,127}/" ~ "[A-Za-z\d!#$&.+-^_]{1,127}" } }, binary) | uri
# Parameters language = element language { language-tag }? pref = element pref { xsd:integer { minInclusive = "1" maxInclusive = "100" } }? pid = element pid { xsd:string { pattern = "\d+(.\d+)?" } }?
# Properties source = element source { pid, pref, uri } name = element name { \text } kind = element kind { element individual { empty } | element group { empty } | element org { empty } | element location { empty } } fn = element fn { language, pid, pref, \text } n = element n { language, element surname { text-list }, element given { text-list },
element prefix { text-list }, element suffix { text-list } } nickname = element nickname { language, pid, pref, text-list } photo = element photo { pid, pref, data } bday = element bday { date-and-or-time | \text } dday = element dday { date-and-or-time | \text } birth = element birth { language, \text } death = element death { language, \text } anniversary = element anniversary { date-and-or-time | \text } sex = element sex { "0" | "1" | "2" | "9" } adr = element adr { language, element geo { uri }?, element tz { \text | uri }?, pid, pref, element pobox { text-list }, element ext { text-list }, element street { text-list }, element locality { text-list }, element region { text-list }, element code { text-list }, element country { text-list } } label = element label { language, pid, pref, \text } tel = element tel { element type { element text { empty }?, element voice { empty }?, element fax { empty }?, element cell { empty }?, element video { empty }?, element pager { empty }? }?, pid, pref, uri } email = element email { pid, pref, \text } impp = element impp { pid, pref, uri } lang = element lang { pid, pref, language-tag } tz = element tz { pid, pref, (\text | uri) } geo = element geo { pid, pref, uri } title = element title { language, pid, pref, \text } role = element role { language, pid, pref, \text }
logo = element logo { language, pid, pref, data } org = element org { language, pid, pref, text-list } member = element member { pid, pref, uri } related = element related { element type { element parent { empty } | element child { empty } | element sibling { empty } | element spouse { empty } | element family { empty } | element friend { empty } | element supervisor { empty } | element supervisee { empty } | element assistant { empty } | element colleague { empty } | element agent { empty } | element emergency { empty } }?, pid, pref, (uri | \text) } categories = element categories { pid, pref, \text } note = element note { language, pid, pref, \text } prodid = element prodid { \text } rev = element rev { timestamp } sort-string = element sort-string { \text } sound = element sound { language, pid, pref, data } uid = element uid { uri } clientpidmap = element clientpidmap { element sourceid { xsd:positiveInteger }, uri } url = element url { pid, pref, uri } class = element class { element PUBLIC { empty } | element PRIVATE { empty } | element CONFIDENTIAL { empty } } key = element key { pid, pref, data } fburl = element fburl { pid, pref, uri } caladruri = element caladruri { pid, pref, uri } caluri = element caluri { pid, pref, uri }
# Top-level grammar group-property = fn | nickname | photo | adr | label | tel | email | impp | lang | tz | geo | title | role | logo | org | related | categories | note | sound | url | key | fburl | caladruri | caluri any-property = group-property | source | name | kind | n | bday | dday | birth | death | anniversary | sex | member | prodid | rev | sort-string | uid | clientpidmap | class start = element vcard { (any-property | element group { attribute name { text }, group-property* })* }
<vcard-4_0.rng>