Парсер XML |
Это парсер XML-документов, написанный на Libretto и использующий библиотеки com/teacode/xrunner
(навигация и построение xml-документов) и com/teacode/sinput
(парсинг текстов).
use com/teacode/sinput as i use com/teacode/xrunner as x use libretto/text use libretto/util def i/Input err(msg:String!) = error(<<%{this.top}/%{this.left}:[%{this.ch}] %{msg}>>!) def i/Input element(parent:x/Elem!):x/Elem! = { fix elem = x/elem("") fix oname = this.opentag(elem) elem.name( oname ) fix cname = this.contents(elem) if (oname != cname) this.err('namesnotcoincide + "-" + oname + "/" + cname?("")) parent.add(elem) } def i/Input opentag(parent:x/Elem!):String! = { this.read("<") this.skipspaceln fix name = if (this.readid("-")) as n {n} else this.err('noname) if (not name) this.err('opentagname) this.skipspaceln util/while (this.letter): this.attribute(parent) if (not this.read(">")) this.err('opentagrangle) name } def i/Input contents(parent:x/Elem!): String! = { var buffer: String* util/while(not this.ch in ("<", i/eof)): { buffer += this.ch this.next } if (this.ch == i/eof) this.err('unexpectedend) parent.add(buffer.*text/join) if (this.closetag) as cname {cname} else { this.element(parent) this.contents(parent) } } def i/Input closetag:String? = { if (not this.readstring("</")) return () this.skipspaceln fix name = this.readid("-") if (not name) this.err('closetagname) this.skipspaceln if (not this.read(">")) this.err('closetagrangle) name } def i/Input attribute(parent:x/Elem!) = { fix key = if (this.readid) as k {k} else this.err('nokey) this.skipspaceln if (not this.read("=")) this.err('attribute) this.skipspaceln if (not this.read(<<">>)) this.err('attrvalue) fix value = this.string parent.addAttr(key, value) } def i/Input string = { var buffer:String* util/while (not this.ch in (<<">>, i/eol, i/eof)): { buffer += this.ch this.next } if (this.ch != <<">>) this.err('string) this.next.skipspaceln buffer.*text/join } // ТОЧКА ВХОДА В ПРОГРАММУ def main = { fix inp = i/Input(xml).skipspaceln fix root = x/elem('root) inp.element(root).string } def xml = << <CATALOG> <PLANT> <COMMON lang="en">Bloodroot</COMMON> <COMMON lang="ru" ha="115">Лапчатка</COMMON> <BOTANICAL>Sanguinaria canadensis</BOTANICAL> <ZONE>4</ZONE> <LIGHT>Mostly Shady</LIGHT> <PRICE>2.44</PRICE> <AVAILABILITY>031599</AVAILABILITY> </PLANT> <PLANT> <COMMON>Columbine</COMMON> <BOTANICAL>Aquilegia canadensis</BOTANICAL> <ZONE>3</ZONE> <LIGHT>Mostly Shady</LIGHT> <PRICE>9.37</PRICE> <AVAILABILITY>030699</AVAILABILITY> </PLANT> <PLANT> <COMMON lang="en">Marsh Marigold</COMMON> <COMMON lang="ru">Калужница болотная</COMMON> <BOTANICAL>Caltha palustris</BOTANICAL> <ZONE>4</ZONE> <LIGHT>Mostly Sunny</LIGHT> <PRICE>6.81</PRICE> <AVAILABILITY>051799</AVAILABILITY> </PLANT> <PLANT> <COMMON>Cowslip</COMMON> <BOTANICAL>Caltha palustris</BOTANICAL> <ZONE>4</ZONE> <LIGHT>Mostly Shady</LIGHT> <PRICE>9.90</PRICE> <AVAILABILITY>030699</AVAILABILITY> </PLANT> </CATALOG> >> def xml1 = << <CATALOG> <PLANT> aaa <COMMON lang="en">Bloodroot</COMMON> <BOTANICAL>Sanguinaria canadensis</BOTANICAL> bbb <ZONE>4</ZONE> ccc </PLANT> </CATALOG> >>