From: Stefan S. <s...@xs...> - 2002-09-21 21:29:36
|
Hi YAMLers, below is the final draft of the article. If we do not receive massive threats of life or limb, we will send it off Tuesday. Thanks for your input. s. =3D=3D=3Dhere we go=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D YAML Ain't Markup Language by Armin R=F6hrl and Stefan Schmiedl YAML (rhyming with "camel") is a new language suitable for encoding data. Its data format is easily parseable by machine and human and especially meant to be used with scripting languages such as Perl, Python or Ruby. YAML is optimized for data serialization, keeping configuration settings,=20 log files, and realizing Internet messaging and filtering.=20 If you think that XML is too verbose and made for computers and not for humans, than YAML is for you. YAML emerged from the union of two efforts:=20 Brian Ingerson had created Data::Denter, a human readable and safely pars= able serialization format for Perl while Clark=20 while Clark Evans and Oren Ben-Kiki worked on simplifying XML. Brian Ingerson gave gave a talk at YAPC on YAML, where Larry Wall was in attendance. Asked about the prospects of YAML in the midst of the XML hype, the creator of Perl responded with: "If I thought Awk and Sed were good enough, I never would have invented Perl". YAML is not going to replace the terabytes of XML out there on the internet, but complement it as a new language for data as used in config files, logging, reporting and data-driven programming. If you are stuck with lots of XML, there is a project going on to convert between XML and YAML [XMLYAML].=20 -------------textbox: YAML design goals----------------- YAML was created according to the following design goals: =3D=3D=3D CODE --- #YAML:1.0 - YAML documents are very easily readable by humans.=20 - Good interaction with scripting languages, as scripting languages are not only good for small hacks, but the rise of Perl, Python and Ruby shows the need for good tools where YAML can help. - YAML uses host languages' native data structures, which is a big advantage over dumb string-based XML. - YAML has a consistent information model.=20 - YAML enables stream-based processing, which is the typical way one works with files or data coming over the network.=20 - YAML is expressive and extensible.=20 - YAML is easy to implement. This is essential for getting acceptance quickly. =3D=3D=3D END -------------------------------------------------------- Learning YAML Keep the highly detailed official specification [spec] for later and try the YAML-Cookbook [Cookbook] first. If you haven't already, you're also going to pick up a bit of Ruby, which won't hurt, either. Below is an example of an invoice expressed in YAML. Structure=20 is shown through indentation (one or more spaces). Sequence=20 items are denoted by a dash, and key value pairs within a map=20 are separated by a colon. =3D=3D=3D CODE --- !clarkevans.com/^invoice invoice: 34843 date : 2001-01-23 bill-to: &addr given : Chris family : Dumars address: lines: | 458 Walkman Dr. Suite #292 city : Royal Oak state : MI postal : 48046 ship-to: *addr product: - sku : BL394D quantity : 4 description : Basketball price : 450.00 - sku : BL4438H quantity : 1 description : Super Hoop price : 2392.00 tax : 251.42 total: 4443.52 comments: > Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338. =3D=3D=3D END There are only a few things to note in addition to what we said above: The billing address is given a label &addr so that we can easily refer to it for shipping with *addr. The ">" in the comments-field denotes unformatted text, which will be line wrapped upon output. Base components Maps in YAML are like hashes in Perl and Ruby, or dictionaries in Python. =3D=3D=3D CODE first name: Julia last name: Smith salary: 44,000 =3D=3D=3D END Sequences in YAML represent things like arrays, lists, tuples, and vectors. =3D=3D=3D CODE - SuSE - Debian - Black Cat =3D=3D=3D END Of course we can combine these as deeply as we want, so we build a mapping between strings and sequences: =3D=3D=3D CODE Countries: - Germany - USA - France Languages: - German - English - French =3D=3D=3D END YAML can also represent multi-line scalars. The two different styles determine whether line feeds get preserved. =3D=3D=3D CODE HTML: > <p>This data is presented on=20 <em>multiple lines</em> in YAML, but=20 it will get folded into <strong>just one</strong> line when it's loaded.</p> YAML: | --- #YAML:1.0 embedding: > It is actually quite easy to embed YAML documents inside YAML documents. =3D=3D=3D END On the other hand, you can use an efficient inline syntax for maps and sequences, too. So =3D=3D=3D CODE Verbose: - name: Fabienne languages:=20 - French - Spanish - name: Fritz languages:=20 - German - English - name: Igor languages:=20 - Russian - English =3D=3D=3D END becomes =3D=3D=3D CODE Compact: - {name: Fabienne, languages: [French, Spanish]} - {name: Fritz, languages: [German, English]} - {name: Igor, languages: [Russian, English]} =3D=3D=3D END Aliases (defined with & and used with *) allow to repeat data elements: =3D=3D=3D CODE Steve: &ScriptingLanguages - Perl - Python - Ruby Ryan: *ScriptingLanguages Claven: [COBOL, Fortran] =3D=3D=3D END To top things off, it is very easy to include multiple YAML documents in one file or string using "---" as document separator. So you can use a stream presenting different YAML documents and let the parser sort them out. =3D=3D=3D CODE town: Baltimore nickname: Orioles --- town: New York teams: - Mets - Yankees --- city: Washington goal: > Washington wants to get a baseball team, so that people in Northern Virginia don't have to drive an=20 hour north to get to the ballpark. =3D=3D=3D END A condensed reference card is shown in the following textbox. Note that the card is a complete YAML-document itself. -------------textbox: reference------------------------- =3D=3D=3D CODE --- #YAML:1.0=20 # A YAML(tm) reference card [Reference] Collection indicators: '? ' : Key indicator. ': ' : Key / value separator. '- ' : Nested series entry indicator. ', ' : Separate in-line branch entries. '[]' : Surround in-line series branch. '{}' : Surround in-line keyed branch. Scalar indicators: '''': Surround in-line unescaped scalar ('' escaped '). '"' : Surround in-line escaped scalar (see escape codes below). '|' : Block scalar indicator. '>' : Folded scalar indicator. '-' : Strip chomp modifier ('|-' or '>-'). '+' : Keep chomp modifier ('|+' or '>+'). int : Explicit indentation modifier ('|10' or '>2'). # Modifiers can be combined ('|2-', '>+10'). Alias indicators: '&' : Anchor property. '*' : Alias indicator. Transfer indicators: '!' : Transfer method indicator. '!!' : Transfer method with private type family. '^' : Establish/use public type family prefix. '|' : Separate public type family from format. Document indicators: '#' : Directive indicator. '---' : Document separator. Misc indicators: ' # ' : Throwaway comment indicator. Scalar types: foo? bar! : String 2002-12-31T18:59:59-05:00 : ISO8601 timestamp (EST) 2002-12-31 18:59:59 Z : Space separated timestamp (UTC) [ 1234, 0x4D2, 02333 ] : [ Decimal int, Hexadecimal int, Octal i= nt ] [ 1,230.15, 12.3015e+02 ] : [ Fixed float, Exponential float ] Escape codes: Numeric : { "\xXX": 8-bit, "\uXXXX": 16-bit, "\UXXXXXXXX": 32-bit } Protective: { "\\": '\', "\"": '"', "\ ": ' ' } C: { "\a": BEL, "\b": BS, "\f": FF, "\n": LF, "\r": CR, "\t": TAB, "\v":= VTAB } Additional: { "\e": ESC, "\z": NUL, "\_": NBSP, "\N": NEL, "\L": LS, "\P= ": PS } =3D=3D=3D END -------------------------------------------------------- YAML versus XML We translated a little example from YAML to XML and did a little bit of counting: Our "typical" YAML document is 522 bytes long, which could be reduced to 436 bytes by using compact notation without losing readability. On the XML side we have 783 bytes for the same data, which can be taken down to a 673 bytes long line, which is quite unreadable. =3D=3D=3D CODE # Plain YAML title: Escape of the Unicorn animations: - title: background sky author: Justyna frames: - file: bg_sky_1.png ms: 500 - file: bg_sky_2.png ms: 500 - title: background water author: Jacek frames: - file: bg_water.png ms: 300 - file: bg_water1.png ms: 200 - file: bg_water2.png ms: 200 - file: bg_water3.png ms: 300 - file: bg_water2.png ms: 200 - file: bg_water1.png ms: 200 # Compact YAML title: Escape of the Unicorn animations: - title: background sky author: Justyna frames: - [file: bg_sky_1.png, ms: 500] - [file: bg_sky_2.png, ms: 500] - title: background water author: Jacek frames: - [file: bg_water.png, ms: 300] - [file: bg_water1.png, ms: 200] - [file: bg_water2.png, ms: 200] - [file: bg_water3.png, ms: 300] - [file: bg_water2.png, ms: 200] - [file: bg_water1.png, ms: 200] # XML <title>Escape of the Unicorn</title> <animations> <animation> <title>0 background sky</title> <author>Justyna</author> <frames> <frame><file>bg_sky_1.png</file><ms>500</ms></frame> <frame><file>bg_sky_2.png</file><ms>500</ms></frame> </frames> </animation> <animation> <title>1 background water</title> <author>Jacek</author> <frames> <frame><file>bg_water.png</file><ms>300</ms></frame> <frame><file>bg_water1.png</file><ms>200</ms></frame> <frame><file>bg_water2.png</file><ms>200</ms></frame> <frame><file>bg_water3.png</file><ms>300</ms></frame> <frame><file>bg_water2.png</file><ms>200</ms></frame> <frame><file>bg_water1.png</file><ms>200</ms></frame> </frames> </animation> </animations> =3D=3D=3D END Interface to scripting languages There's definitely cooperation among the YAML authors to make a similar interface, but they also try to create interfaces that feel native to the language at hand. So, you are going to find "dump" and "load" everywhere, but the Python version returns an iterator, while the Perl implementation answers a list. Due to a language-neutral testing suite the various implementations are benchmarked to determine interoperability between implementations.=20 -------------textbox: Python sample code---------------- The following Python samples originate with the Python bindings written by Steve Howell. You can easily access the YAML changelog: =3D=3D=3D CODE import yaml, string readme =3D yaml.loadFile("README") print "README" for item in readme.next(): print item print "\n\nCONTRIBUTORS" for person in readme.next()['contributors']: print "=3D=3D=3D%s=3D=3D=3D" % person['who'] print person['why?'] print print "\n\n" print "CHANGELOG:\n" print list(yaml.loadFile("CHANGELOG")) print "\n\n" =3D=3D=3D END To create a YAML representation of an object, you have to implement a to_yaml-method preparing the necessary information. The actual transformation takes place with one of the dump-methods. =3D=3D=3D CODE import yaml, string class Person: def __init__(self, fname, lname, salary): self.fname =3D fname self.lname =3D lname self.salary =3D salary def to_yaml(self): return ({ 'first name': self.fname, 'last name': self.lname, 'salary': self.salary }, '!!Person') mrBarson =3D Person('Foo', 'Barson', 20000) mrDoe =3D Person('John', 'Doe', None) print yaml.dump([mrBarson, mrDoe]) =3D=3D=3D END You can also dump multiple YAML documents to a single file. =3D=3D=3D CODE import yaml, string file =3D open('DEMO_OUTPUT.TXT', 'w') yaml.dumpToFile(file,=20 {'source': "First document from python"}, [ 'second', 'document', ], 'Third document' =20 ) file.close() =3D=3D=3D END -------------------------------------------------------- The Ruby implementation For Ruby developers, YAML is a natural fit for object serialization and general data storage, as their semantics are similiar. YAML4R is a fully-featured YAML parser and emitter for Ruby. Use it as a drop-in replacement for PStore, or use one of its several APIs to store object data in the friendly and readable YAML style. The implementation is done by "why the lucky stiff". YAML4R requires a current version of Racc, which in turn requires Ruby (>=3D1.4) and a C compiler. To enable Unicode support, you must have a current version of the Iconv module for Ruby. Ruby encourages objects to have their own exporting methods. Hence, YAML.rb adds #to_yaml methods for built-in types: The NilClass, FalseClass, TrueClass, Symbol, Range, Numeric, Date, Time, Regexp, String, Array, and Hash all get their implementation of the #to_yaml method. And using it is just a breeze: =3D=3D=3D CODE require 'yaml' h =3D { 'test' =3D> 12, 'another' =3D> 13 } puts h.to_yaml =3D=3D=3D END Although you'll often want to store multiple YAML documents in a single file, YAML.rb has a simplified mechanism for loading and storing a single document in a single file.=20 =3D=3D=3D CODE require 'yaml' obj =3D YAML::load(File::open("/tmp/yaml.store.1")) =3D=3D=3D END It does not matter, where the data originates, as the Parser also accepts String objects through the same function. So you can even do: =3D=3D=3D CODE require 'yaml' obj =3D YAML::load( <<EOY --- #YAML:1.0 - armless - falling - birds EOY ) p obj #=3D> [ 'armless', 'falling', 'birds' ] =3D=3D=3D END Parsing multiple documents from a YAML stream When reading YAML from a socket or a pipe, you should consider using the event-based parser, which will parse documents one at a time. =3D=3D=3D CODE require 'yaml' log =3D File.open( "/var/log/apache.yaml" ) yp =3D YAML::Parser.new.parse_documents( log ) { |doc| puts "#{doc['at']} #{doc['type']} #{doc['url}" } =3D=3D=3D END Right now there are at least three active Ruby-YAML projects: Yod (the equivalent-to-be of pod), the Endertromb web server (to be released soonish) and ONI [ONI], which uses YAML to serialize objects to pass them between Ruby apps. "why" also mentionned that a good YAML application would be a messaging protocol similiar to Jabber. The handy thing about implementing a protocol in Jabber is that you can pass object instances around simply. So an invite message might be: =3D=3D=3D CODE --- !jabber.org,2003/^message to: yam...@ja... from: wh...@wh... action: invite:yo...@yo... body: > Hey, this is just an example, but at least it illustrates the point. =3D=3D=3D END Not only is it completely readable, but it will load as an object in each of the implementations. In Ruby, to handle this message you could just load it: =3D=3D=3D CODE msg =3D YAML::load(message_str) puts msg.to #=3D> 'yam...@ja...' =3D=3D=3D END In Python, there are similiar ways to use handlers to yield a class: =3D=3D=3D CODE class MessageLoader: def resolveType(self, value, transfer): if transfer =3D=3D "!jabber.org,2003/message" return Message(data) msg =3D yaml.load(message_str, MessageLoader()).next() print msg.to =3D=3D=3D END The point is: the YAML team is working toward YAML as a central means of data-sharing. Not only would the protocol be completely portable, but the interfaces to use the protocol have no barrier to entry. Once you have learned how to load and emit, then you're strictly dealing with objects which are native to the language you are using. As an example, Stefan has written a little Ruby/YAML-utility to be found at [WhereAmI] to keep on top of his everday programming tasks. The Java implementation The Java parser is still in an early stage; it is not in any usable state, but Rolf Veen is working on a new release.=20 He will soon inform the world of a new version. Conclusion YAML is very young and moving ahead virtually every day. We recommend you to join the mailinglist [MailingList] and ask your questions to the yaml-core team directly. It is a young team of enthusiasts that want to create something different than XML.=20 While XML is produced by big committees that pretend to be think-tanks, YAML can be adapted to new ideas at break-neck speed within hours. In open source projects it makes big fun to watch the dynamics of new good ideas. YAML might achieve a good degree of acceptance and make it into the business world, as was the case with PHP, a tool that at first just made sense to developers. And when we show YAML to developers, they can see it sparkles. ----------Brian Ingerson on Perl and YAML -------------- > Are there distinct advantages or problems (perl-related) > you experienced while working on the module? In some ways, YAML is a superset of Perl data structures. Most notably in regard to structured hash keys. Perl 5 doesn't have them; every key is a string. Python allows objects as hash (dictionary keys) and Ruby sup= ports just about anything including objects. Perl 6 will probably follow suite.=20 We decided to take the high road with YAML. Any type of node can be expressed as a mapping key. This is a problem for Perl 5. I decided to support them as best as possible, because that's the Perl way. Luckily, for any of Perl's inherent weaknesses it seems to have plenty of strengths to make up for it. The tie() facility is one such example. It allows you to create more complex structures than are readily available, = and use them like normal hashes, arrays and scalars.=20 I created a class called YAML::Node that is special to YAML.pm. It wraps around regular Perl node, but allows YAML to attach extra information to = it. Using this, and a technique called "shadowing", I am able to roundtrip YA= ML documents containing structured keys transparently in Perl 5. > Are there any applications where you already used YAML? > Do you expect any difficulties keeping these in sync > with the evolving standard? No big ones. At least not in the public domain. I've tried to keep a rather low profile for YAML, because it was evolving so fast. There are early adopters of course. The new CPAN MakeMaker replacement, Module::Build, uses YAML to store meta data into every CPAN module distribution. But as far as I know, it uses a rather stable subset and I don't foresee any breakage. As soon as the spec is frozen, I'll promote the heck out of YAML. Of cour= se, this article might change everything. > Do you know some "famous" (whatever that means) users of YAML? Hmm. I've definitely pitched YAML to some somewhat famous people. The brilliant people at ActiveState definitely have heard an earful from the days when I used to work there. I believe that they use it for some of their internal processes. This summer I got the chance to present a talk at YAPC on YAML. Larry Wall was in attendance. I asked him afterwards if he thought I was crazy, given the fact that everyone seems concentrated on XML. He said, "If I thought Awk and Sed were good enough, I never would have invented Perl". > Do you think YAML will make it into the world of webservices? I think YAML will ooze into just about every computing crevice imaginable. People will do it because it's simply a pleasure to work with on small, e= very day type tasks. People always want to take those technologies and run wit= h them as far they can go. Luckily, we've taken the time to make sure YAML = can support enterprise applications as well.=20 I don't feel a need to push YAML in any single direction. I want it to find lives of its own. People have already expressed interest in using YAML as a transport for SOAP or doing YAML/RPC. I simply say, "sounds good". > What is your favourite (short) YAML-Perl code snipplet? It is definitely: perl -MYAML -e '$YAML::DumpCode =3D 1; print Dump *::' This will produce several thousand lines of output. It is a full dump of the Perl symbol table, complete with typeglobs, coderefs, blessed objects and even filehandles. If you can understand the entire contents of this dump, you are definitely a candidate for Perl god status. ------------------------------------------------------------ Acknowledgements Many thanks go the YAML team. Material and advice from Brian Ingerson, Rolf Veen, Steve Howell, why, Clark Evans and many others was used for or included in this article. Links =3D=3D=3D=3D=3D - [yaml] http://www.yaml.org/ - [denter] http://search.cpan.org/search?module=3DData::Denter - [wiki] http://wiki.yaml.org/yamlwiki/ - [spec] http://www.yaml.org/spec/ - [java] http://helide.com/g/yaml/ - [Reference] http://www.yaml.org/refcard.html - [Cookbook] http://yaml4r.sf.net/cookbook/ - [MailingList] http://lists.sourceforge.net/lists/listinfo/yaml-core - [SlideShow ] http://mountainwebtools.com/SlideShowell/rSlide-0.html - [XMLYAML] http://wiki.yaml.org/yamlwiki/XmlYaml - [ONI] http://www.ruby-lang.org/en/raa-list.rhtml?name=3DTomsLib |
From: Brian I. <in...@tt...> - 2002-09-22 03:39:48
|
On 21/09/02 23:29 +0200, Stefan Schmiedl wrote: > Hi YAMLers, >=20 > below is the final draft of the article. > If we do not receive massive threats of life or limb, > we will send it off Tuesday. Looks pretty good. I have a few comments below. > Thanks for your input. >=20 > s. >=20 >=20 > =3D=3D=3Dhere we go=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D >=20 > YAML Ain't Markup Language >=20 > by Armin R=F6hrl and Stefan Schmiedl >=20 > YAML (rhyming with "camel") is a new language suitable for xxxxxxxx suitable - implies that it isn't the primary purpose > encoding data. Its data format is easily parseable by parsable (I think. Neither form is valid at m-w.com) > machine and human and especially meant to be used with > scripting languages such as Perl, Python or Ruby. YAML is > optimized for data serialization, keeping configuration settings,=20 > log files, and realizing Internet messaging and filtering.=20 >=20 > If you think that XML is too verbose and made for computers > and not for humans, than YAML is for you. YAML emerged from > the union of two efforts:=20 > Brian Ingerson had created Data::Denter, a human readable and safely pa= rsable > serialization format for Perl while Clark=20 xxxxxxxxxxx repeat > while Clark Evans and Oren Ben-Kiki worked on simplifying XML. >=20 >=20 > Brian Ingerson gave gave a talk at YAPC on YAML, where Larry xxxx another dup I would rephrase as: Brian Ingerson recently gave a talk on YAML at the Yet Another Perl Conference, where Larry > Wall was in attendance. Asked about the prospects of YAML in > the midst of the XML hype, the creator of Perl responded > with: "If I thought Awk and Sed were good enough, I never would have ^had this is a paraphrase anyway... > invented Perl". created Perl is more of a creation than an invention. (I hate to put words in Larry's mouth) >=20 >=20 > YAML is not going to replace the terabytes of XML out there > on the internet, but complement it as a new language for > data as used in config files, logging, reporting and > data-driven programming. If you are stuck with lots of XML, > there is a project going on to convert between XML and YAML > [XMLYAML].=20 >=20 >=20 > -------------textbox: YAML design goals----------------- > YAML was created according to the following design goals: >=20 > =3D=3D=3D CODE > --- #YAML:1.0 > - YAML documents are very easily readable by humans.=20 > - Good interaction with scripting languages, as scripting > languages are not only good for small hacks, but the rise > of Perl, Python and Ruby shows the need for good tools > where YAML can help. > - YAML uses host languages' native data structures, which is > a big advantage over dumb string-based XML. > - YAML has a consistent information model.=20 > - YAML enables stream-based processing, which is the typical > way one works with files or data coming over the network.=20 > - YAML is expressive and extensible.=20 > - YAML is easy to implement. This is essential for getting > acceptance quickly. > =3D=3D=3D END > -------------------------------------------------------- I'm not sure that the YAML team would agree with the above paraphrasing. = I especially am uncomfortable with calling XML dumb. In fact, XML doesn't e= ven play a part in our stated design goals. Perhaps you should just quote the spec verbatim in this example. I don't mind editorial, but not when it lo= oks like it came from us. >=20 > Learning YAML >=20 > Keep the highly detailed official specification [spec] for > later and try the YAML-Cookbook [Cookbook] first. If you > haven't already, you're also going to pick up a bit of Ruby, > which won't hurt, either. >=20 > Below is an example of an invoice expressed in YAML. Structure=20 > is shown through indentation (one or more spaces). Sequence=20 > items are denoted by a dash, and key value pairs within a map=20 > are separated by a colon. >=20 > =3D=3D=3D CODE > --- !clarkevans.com/^invoice > invoice: 34843 > date : 2001-01-23 > bill-to: &addr > given : Chris > family : Dumars > address: > lines: | > 458 Walkman Dr. > Suite #292 > city : Royal Oak > state : MI > postal : 48046 > ship-to: *addr > product: > - sku : BL394D > quantity : 4 > description : Basketball > price : 450.00 > - sku : BL4438H > quantity : 1 > description : Super Hoop > price : 2392.00 > tax : 251.42 > total: 4443.52 > comments: > > Late afternoon is best. > Backup contact is Nancy > Billsmer @ 338-4338. > =3D=3D=3D END >=20 > There are only a few things to note in addition to what we > said above: The billing address is given a label &addr so > that we can easily refer to it for shipping with *addr. The > ">" in the comments-field denotes unformatted text, which > will be line wrapped upon output. >=20 > Base components >=20 > Maps in YAML are like hashes in Perl and Ruby, or > dictionaries in Python. >=20 > =3D=3D=3D CODE > first name: Julia > last name: Smith > salary: 44,000 > =3D=3D=3D END >=20 > Sequences in YAML represent things like arrays, lists, > tuples, and vectors. >=20 > =3D=3D=3D CODE > - SuSE > - Debian > - Black Cat > =3D=3D=3D END >=20 > Of course we can combine these as deeply as we want, so we > build a mapping between strings and sequences: >=20 > =3D=3D=3D CODE > Countries: > - Germany > - USA > - France > Languages: > - German > - English > - French > =3D=3D=3D END >=20 > YAML can also represent multi-line scalars. The two > different styles determine whether line feeds get preserved. >=20 > =3D=3D=3D CODE > HTML: > > <p>This data is presented on=20 > <em>multiple lines</em> in YAML, but=20 > it will get folded into <strong>just one</strong> > line when it's loaded.</p> > YAML: | > --- #YAML:1.0 > embedding: > > It is actually quite easy to embed > YAML documents inside YAML documents. > =3D=3D=3D END >=20 > On the other hand, you can use an efficient inline syntax > for maps and sequences, too. So >=20 > =3D=3D=3D CODE > Verbose: > - name: Fabienne > languages:=20 > - French > - Spanish > - name: Fritz > languages:=20 > - German > - English > - name: Igor > languages:=20 > - Russian > - English > =3D=3D=3D END >=20 > becomes >=20 > =3D=3D=3D CODE > Compact: > - {name: Fabienne, languages: [French, Spanish]} > - {name: Fritz, languages: [German, English]} > - {name: Igor, languages: [Russian, English]} > =3D=3D=3D END - {name: Fabienne, languages: [French, Spanish]} - {name: Fritz, languages: [German, English]} - {name: Igor, languages: [Russian, English]} cosmetics =20 >=20 > Aliases (defined with & and used with *) allow to repeat > data elements: >=20 > =3D=3D=3D CODE > Steve: &ScriptingLanguages > - Perl > - Python > - Ruby > Ryan: *ScriptingLanguages > Claven: [COBOL, Fortran] > =3D=3D=3D END >=20 > To top things off, it is very easy to include multiple YAML > documents in one file or string using "---" as document > separator. So you can use a stream presenting different YAML > documents and let the parser sort them out. >=20 > =3D=3D=3D CODE > town: Baltimore > nickname: Orioles > --- > town: New York > teams: > - Mets > - Yankees > --- > city: Washington > goal: > > Washington wants to get a baseball > team, so that people in Northern > Virginia don't have to drive an=20 > hour north to get to the ballpark. > =3D=3D=3D END >=20 > A condensed reference card is shown in the following > textbox. Note that the card is a complete YAML-document > itself. >=20 > -------------textbox: reference------------------------- > =3D=3D=3D CODE > --- #YAML:1.0=20 > # A YAML(tm) reference card [Reference] >=20 > Collection indicators: > '? ' : Key indicator. > ': ' : Key / value separator. > '- ' : Nested series entry indicator. > ', ' : Separate in-line branch entries. > '[]' : Surround in-line series branch. > '{}' : Surround in-line keyed branch. >=20 > Scalar indicators: > '''': Surround in-line unescaped scalar ('' escaped '). > '"' : Surround in-line escaped scalar (see escape codes below). > '|' : Block scalar indicator. > '>' : Folded scalar indicator. > '-' : Strip chomp modifier ('|-' or '>-'). > '+' : Keep chomp modifier ('|+' or '>+'). > int : Explicit indentation modifier ('|10' or '>2'). > # Modifiers can be combined ('|2-', '>+10'). >=20 > Alias indicators: > '&' : Anchor property. > '*' : Alias indicator. >=20 > Transfer indicators: > '!' : Transfer method indicator. > '!!' : Transfer method with private type family. > '^' : Establish/use public type family prefix. > '|' : Separate public type family from format. >=20 > Document indicators: > '#' : Directive indicator. > '---' : Document separator. >=20 > Misc indicators: > ' # ' : Throwaway comment indicator. >=20 > Scalar types: > foo? bar! : String > 2002-12-31T18:59:59-05:00 : ISO8601 timestamp (EST) > 2002-12-31 18:59:59 Z : Space separated timestamp (UTC) > [ 1234, 0x4D2, 02333 ] : [ Decimal int, Hexadecimal int, Octal= int ] > [ 1,230.15, 12.3015e+02 ] : [ Fixed float, Exponential float ] >=20 > Escape codes: > Numeric : { "\xXX": 8-bit, "\uXXXX": 16-bit, "\UXXXXXXXX": 32-bit } > Protective: { "\\": '\', "\"": '"', "\ ": ' ' } > C: { "\a": BEL, "\b": BS, "\f": FF, "\n": LF, "\r": CR, "\t": TAB, "\v= ": VTAB } > Additional: { "\e": ESC, "\z": NUL, "\_": NBSP, "\N": NEL, "\L": LS, "= \P": PS } I'm about to propose \0 to replace \z. And ' # ' is still questionable. I'd just leace it as is though. It's a reasonable example. Nobody's going to use this article as a reference. > =3D=3D=3D END > -------------------------------------------------------- >=20 > YAML versus XML >=20 > We translated a little example from YAML to XML and did a > little bit of counting: Our "typical" YAML document is 522 > bytes long, which could be reduced to 436 bytes by using > compact notation without losing readability. On the XML > side we have 783 bytes for the same data, which can be > taken down to a 673 bytes long line, which is quite > unreadable. >=20 > =3D=3D=3D CODE > # Plain YAML > title: Escape of the Unicorn > animations: > - title: background sky > author: Justyna > frames: > - file: bg_sky_1.png > ms: 500 > - file: bg_sky_2.png > ms: 500 > - title: background water > author: Jacek > frames: > - file: bg_water.png > ms: 300 > - file: bg_water1.png > ms: 200 > - file: bg_water2.png > ms: 200 > - file: bg_water3.png > ms: 300 > - file: bg_water2.png > ms: 200 > - file: bg_water1.png > ms: 200 >=20 > # Compact YAML > title: Escape of the Unicorn > animations: > - > title: background sky > author: Justyna > frames: > - [file: bg_sky_1.png, ms: 500] > - [file: bg_sky_2.png, ms: 500] > - > title: background water > author: Jacek > frames: > - [file: bg_water.png, ms: 300] > - [file: bg_water1.png, ms: 200] > - [file: bg_water2.png, ms: 200] > - [file: bg_water3.png, ms: 300] > - [file: bg_water2.png, ms: 200] > - [file: bg_water1.png, ms: 200] Oren's seq-in-map proposal could reduce this by 10 more bytes :) >=20 > # XML > <title>Escape of the Unicorn</title> > <animations> > <animation> > <title>0 background sky</title> > <author>Justyna</author> > <frames> > <frame><file>bg_sky_1.png</file><ms>500</ms></frame> > <frame><file>bg_sky_2.png</file><ms>500</ms></frame> > </frames> > </animation> > <animation> > <title>1 background water</title> > <author>Jacek</author> > <frames> > <frame><file>bg_water.png</file><ms>300</ms></frame> > <frame><file>bg_water1.png</file><ms>200</ms></frame> > <frame><file>bg_water2.png</file><ms>200</ms></frame> > <frame><file>bg_water3.png</file><ms>300</ms></frame> > <frame><file>bg_water2.png</file><ms>200</ms></frame> > <frame><file>bg_water1.png</file><ms>200</ms></frame> > </frames> > </animation> > </animations> > =3D=3D=3D END >=20 >=20 > Interface to scripting languages >=20 > There's definitely cooperation among the YAML authors to > make a similar interface, but they also try to create > interfaces that feel native to the language at hand. So, you > are going to find "dump" and "load" everywhere, but the > Python version returns an iterator, while the Perl > implementation answers a list. >=20 > Due to a language-neutral testing suite the various s/Due/Thanks/ > implementations are benchmarked to determine > interoperability between implementations.=20 >=20 > -------------textbox: Python sample code---------------- > The following Python samples originate with the Python > bindings written by Steve Howell. >=20 > You can easily access the YAML changelog: >=20 > =3D=3D=3D CODE > import yaml, string >=20 > readme =3D yaml.loadFile("README") > print "README" > for item in readme.next(): > print item > print "\n\nCONTRIBUTORS" > for person in readme.next()['contributors']: > print "=3D=3D=3D%s=3D=3D=3D" % person['who'] > print person['why?'] > print > print "\n\n" > print "CHANGELOG:\n" > print list(yaml.loadFile("CHANGELOG")) > print "\n\n" > =3D=3D=3D END >=20 > To create a YAML representation of an object, you have > to implement a to_yaml-method preparing the necessary > information. The actual transformation takes place with > one of the dump-methods. >=20 > =3D=3D=3D CODE > import yaml, string >=20 > class Person: > def __init__(self, fname, lname, salary): > self.fname =3D fname > self.lname =3D lname > self.salary =3D salary > def to_yaml(self): > return ({ > 'first name': self.fname, > 'last name': self.lname, > 'salary': self.salary > }, '!!Person') >=20 > mrBarson =3D Person('Foo', 'Barson', 20000) > mrDoe =3D Person('John', 'Doe', None) > print yaml.dump([mrBarson, mrDoe]) > =3D=3D=3D END >=20 > You can also dump multiple YAML documents to a single > file. >=20 > =3D=3D=3D CODE > import yaml, string >=20 > file =3D open('DEMO_OUTPUT.TXT', 'w') > yaml.dumpToFile(file,=20 > {'source': "First document from python"}, > [ > 'second', > 'document', > ], > 'Third document' =20 > ) > file.close() > =3D=3D=3D END > -------------------------------------------------------- >=20 >=20 > The Ruby implementation >=20 > For Ruby developers, YAML is a natural fit for object > serialization and general data storage, as their semantics > are similiar. YAML4R is a fully-featured YAML parser and > emitter for Ruby. Use it as a drop-in replacement for > PStore, or use one of its several APIs to store object data > in the friendly and readable YAML style. The implementation > is done by "why the lucky stiff". >=20 > YAML4R requires a current version of Racc, which in > turn requires Ruby (>=3D1.4) and a C compiler. To enable > Unicode support, you must have a current version of the > Iconv module for Ruby. >=20 > Ruby encourages objects to have their own exporting methods. > Hence, YAML.rb adds #to_yaml methods for built-in types: > The NilClass, FalseClass, TrueClass, Symbol, Range, > Numeric, Date, Time, Regexp, String, Array, and Hash all > get their implementation of the #to_yaml method. And using > it is just a breeze: >=20 > =3D=3D=3D CODE > require 'yaml' > h =3D { 'test' =3D> 12, 'another' =3D> 13 } > puts h.to_yaml > =3D=3D=3D END >=20 > Although you'll often want to store multiple YAML documents > in a single file, YAML.rb has a simplified mechanism for > loading and storing a single document in a single file.=20 >=20 > =3D=3D=3D CODE > require 'yaml' > obj =3D YAML::load(File::open("/tmp/yaml.store.1")) > =3D=3D=3D END >=20 > It does not matter, where the data originates, as the Parser > also accepts String objects through the same function. So > you can even do: >=20 > =3D=3D=3D CODE > require 'yaml' > obj =3D YAML::load( <<EOY > --- #YAML:1.0 > - armless > - falling > - birds > EOY > ) > p obj > #=3D> [ 'armless', 'falling', 'birds' ] > =3D=3D=3D END >=20 > Parsing multiple documents from a YAML stream >=20 > When reading YAML from a socket or a pipe, you should > consider using the event-based parser, which will parse > documents one at a time. >=20 > =3D=3D=3D CODE > require 'yaml' > log =3D File.open( "/var/log/apache.yaml" ) > yp =3D YAML::Parser.new.parse_documents( log ) { |doc| > puts "#{doc['at']} #{doc['type']} #{doc['url}" > } > =3D=3D=3D END >=20 > Right now there are at least three active Ruby-YAML > projects: Yod (the equivalent-to-be of pod), the Endertromb > web server (to be released soonish) and ONI [ONI], which > uses YAML to serialize objects to pass them between Ruby > apps. >=20 > "why" also mentionned that a good YAML application would be > a messaging protocol similiar to Jabber. The handy thing > about implementing a protocol in Jabber is that you can pass > object instances around simply. So an invite message might > be: >=20 > =3D=3D=3D CODE > --- !jabber.org,2003/^message > to: yam...@ja... > from: wh...@wh... > action: invite:yo...@yo... > body: > > Hey, this is just an example, > but at least it illustrates the > point. > =3D=3D=3D END >=20 > Not only is it completely readable, but it will load as an > object in each of the implementations. In Ruby, to handle > this message you could just load it: >=20 > =3D=3D=3D CODE > msg =3D YAML::load(message_str) > puts msg.to > #=3D> 'yam...@ja...' > =3D=3D=3D END >=20 > In Python, there are similiar ways to use handlers to yield > a class: >=20 > =3D=3D=3D CODE > class MessageLoader: > def resolveType(self, value, transfer): > if transfer =3D=3D "!jabber.org,2003/message" > return Message(data) > msg =3D yaml.load(message_str, MessageLoader()).next() > print msg.to > =3D=3D=3D END >=20 > The point is: the YAML team is working toward YAML as a > central means of data-sharing. Not only would the protocol > be completely portable, but the interfaces to use the > protocol have no barrier to entry. Once you have learned > how to load and emit, then you're strictly dealing with > objects which are native to the language you are using. >=20 > As an example, Stefan has written a little Ruby/YAML-utility to be > found at [WhereAmI] to keep on top of his everday > programming tasks. >=20 The Perl Implementation Brian Ingerson wrote the first fully functional YAML implementation, YAML.pm, in December 2001. It's basic usage is similar to that of the ubiquitous Data::Dumper module: use YAML; $yaml_string =3D Dump(@data_objects); @new_data_objects =3D Load($yaml_string); YAML.pm is capable of roundtripping the same level of data structures as Data::Dumper, including blessed objects, code references and recursive da= ta.=20 But it doesn't stop there. YAML.pm can also serialize typeglobs, regular expressions and even filehandles. And like the Python and Perl implementations, it also supports the to_yaml and from_yaml interface tha= t allows object classes to specify how they should be represented in YAML. One nifty feature of YAML.pm is that it ships with a small interactive program called 'ysh' (The YAML Shell). When a user types in Perl code, th= ey get back YAML, and when they type in YAML, they get back Perl. Here is a sample session: ysh > $x =3D 1; @x =3D (2, 3); *x # the typeglob for 'x' =20 --- #YAML:1.0 !perl/glob: PACKAGE: main NAME: x SCALAR: 1 ARRAY: - 2 - 3 ysh > --- yaml> foo: &xxx yaml> - bar yaml> - *xxx yaml> ... $VAR1 =3D { 'foo' =3D> [ 'bar', $VAR1->{'foo'} ] }; >=20 > The Java implementation >=20 > The Java parser is still in an early stage; it is not in any > usable state, but Rolf Veen is working on a new release.=20 > He will soon inform the world of a new version. >=20 >=20 > Conclusion >=20 > YAML is very young and moving ahead virtually every day. We > recommend you to join the mailinglist [MailingList] and ask > your questions to the yaml-core team directly. It is a > young team of enthusiasts that want to create something > different than XML.=20 >=20 > While XML is produced by big committees that pretend to be > think-tanks, YAML can be adapted to new ideas at break-neck > speed within hours. In open source projects it makes big fun > to watch the dynamics of new good ideas. >=20 > YAML might achieve a good degree of acceptance and make it > into the business world, as was the case with PHP, a tool > that at first just made sense to developers. And when we > show YAML to developers, they can see it sparkles. >=20 >=20 >=20 > ----------Brian Ingerson on Perl and YAML -------------- >=20 >=20 > > Are there distinct advantages or problems (perl-related) > > you experienced while working on the module? >=20 > In some ways, YAML is a superset of Perl data structures. Most notably > in regard to structured hash keys. Perl 5 doesn't have them; every key > is a string. Python allows objects as hash (dictionary keys) and Ruby s= upports > just about anything including objects. Perl 6 will probably follow This paragraph reads funny because you use the word "objects" twice and awkwardly. I would rephrase, but everytime I speak up on this I get it wr= ong. Anyone else care to help? > suite.=20 >=20 > We decided to take the high road with YAML. Any type of node can be > expressed as a mapping key. This is a problem for Perl 5. I decided to > support them as best as possible, because that's the Perl way. >=20 > Luckily, for any of Perl's inherent weaknesses it seems to have plenty = of > strengths to make up for it. The tie() facility is one such example. It > allows you to create more complex structures than are readily available= , and > use them like normal hashes, arrays and scalars.=20 >=20 > I created a class called YAML::Node that is special to YAML.pm. It wrap= s > around regular Perl node, but allows YAML to attach extra information t= o it. > Using this, and a technique called "shadowing", I am able to roundtrip = YAML > documents containing structured keys transparently in Perl 5. >=20 > > Are there any applications where you already used YAML? > > Do you expect any difficulties keeping these in sync > > with the evolving standard? >=20 > No big ones. At least not in the public domain. I've tried to keep a > rather low profile for YAML, because it was evolving so fast. There are > early adopters of course. The new CPAN MakeMaker replacement, > Module::Build, uses YAML to store meta data into every CPAN module > distribution. But as far as I know, it uses a rather stable subset and = I > don't foresee any breakage. >=20 > As soon as the spec is frozen, I'll promote the heck out of YAML. Of co= urse, > this article might change everything. >=20 > > Do you know some "famous" (whatever that means) users of YAML? >=20 > Hmm. I've definitely pitched YAML to some somewhat famous people. The > brilliant people at ActiveState definitely have heard an earful from th= e > days when I used to work there. I believe that they use it for some of > their internal processes. >=20 > This summer I got the chance to present a talk at YAPC on YAML. Larry > Wall was in attendance. I asked him afterwards if he thought I was > crazy, given the fact that everyone seems concentrated on XML. He > said, "If I thought Awk and Sed were good enough, I never would have > invented Perl". >=20 > > Do you think YAML will make it into the world of webservices? >=20 > I think YAML will ooze into just about every computing crevice imaginab= le. > People will do it because it's simply a pleasure to work with on small,= every > day type tasks. People always want to take those technologies and run w= ith > them as far they can go. Luckily, we've taken the time to make sure YAM= L can > support enterprise applications as well.=20 >=20 > I don't feel a need to push YAML in any single direction. I want it > to find lives of its own. People have already expressed interest in > using YAML as a transport for SOAP or doing YAML/RPC. I simply say, > "sounds good". >=20 > > What is your favourite (short) YAML-Perl code snipplet? >=20 > It is definitely: >=20 > perl -MYAML -e '$YAML::DumpCode =3D 1; print Dump *::' >=20 > This will produce several thousand lines of output. It is a full dump o= f > the Perl symbol table, complete with typeglobs, coderefs, blessed > objects and even filehandles. If you can understand the entire contents > of this dump, you are definitely a candidate for Perl god status. >=20 > ------------------------------------------------------------ >=20 > Acknowledgements >=20 > Many thanks go the YAML team. Material and advice from Brian Ingerson, > Rolf Veen, Steve Howell, why, Clark Evans and many others was used for > or included in this article. Looks great! Please send a revision if you apply the changes. Cheers, Brian >=20 >=20 > Links > =3D=3D=3D=3D=3D > - [yaml] http://www.yaml.org/ > - [denter] http://search.cpan.org/search?module=3DData::Denter > - [wiki] http://wiki.yaml.org/yamlwiki/ > - [spec] http://www.yaml.org/spec/ > - [java] http://helide.com/g/yaml/ > - [Reference] http://www.yaml.org/refcard.html > - [Cookbook] http://yaml4r.sf.net/cookbook/ > - [MailingList] http://lists.sourceforge.net/lists/listinfo/yaml-core > - [SlideShow ] http://mountainwebtools.com/SlideShowell/rSlide-0.html > - [XMLYAML] http://wiki.yaml.org/yamlwiki/XmlYaml > - [ONI] http://www.ruby-lang.org/en/raa-list.rhtml?name=3DTomsLib >=20 >=20 > ------------------------------------------------------- > This sf.net email is sponsored by:ThinkGeek > Welcome to geek heaven. > http://thinkgeek.com/sf > _______________________________________________ > Yaml-core mailing list > Yam...@li... > https://lists.sourceforge.net/lists/listinfo/yaml-core |
From: Ned K. <ne...@bi...> - 2002-09-22 04:06:12
|
On Saturday 21 September 2002 08:39 pm, Brian Ingerson wrote: > > In some ways, YAML is a superset of Perl data structures. Most > > notably in regard to structured hash keys. Perl 5 doesn't have > > them; every key is a string. Python allows objects as hash > > (dictionary keys) and Ruby supports just about anything including > > objects. Perl 6 will probably follow > > This paragraph reads funny because you use the word "objects" twice > and awkwardly. I would rephrase, but everytime I speak up on this I > get it wrong. Anyone else care to help? > > In some ways, YAML is a superset of Perl data structures. Most > > notably in regard to structured hash keys. Perl 5 doesn't have > > them; every key is a string. Python allows objects as hash > > (dictionary keys) and Ruby supports just about anything including > > objects. Perl 6 will probably follow YAML can express structures that don't map easily to Perl data=20 structures. One important example of this is YAML's ability to=20 represent dictionary keys that have more structure than mere strings.=20 Perl 5 only allows strings as dictionary keys. --=20 Ned Konz http://bike-nomad.com GPG key ID: BEEA7EFE |
From: Brian I. <in...@tt...> - 2002-09-22 06:21:55
|
On 21/09/02 21:05 -0700, Ned Konz wrote: > On Saturday 21 September 2002 08:39 pm, Brian Ingerson wrote: > > > In some ways, YAML is a superset of Perl data structures. Most > > > notably in regard to structured hash keys. Perl 5 doesn't have > > > them; every key is a string. Python allows objects as hash > > > (dictionary keys) and Ruby supports just about anything including > > > objects. Perl 6 will probably follow > > > > This paragraph reads funny because you use the word "objects" twice > > and awkwardly. I would rephrase, but everytime I speak up on this I > > get it wrong. Anyone else care to help? > > > > In some ways, YAML is a superset of Perl data structures. Most > > > notably in regard to structured hash keys. Perl 5 doesn't have > > > them; every key is a string. Python allows objects as hash > > > (dictionary keys) and Ruby supports just about anything including > > > objects. Perl 6 will probably follow > > YAML can express structures that don't map easily to Perl data > structures. One important example of this is YAML's ability to > represent dictionary keys that have more structure than mere strings. > Perl 5 only allows strings as dictionary keys. Thanks Ned. But it was this sentence that was bugging me: Python allows objects as hash (dictionary keys) and Ruby supports just about anything including objects. I think I would write it as: Python allows tuples and objects to be hash (dictionary) keys and Ruby supports just about everything as a hash key. I'd leave the rest as i originally wrote it. No offense Ned. Your version is better written but it's not exactly the meaning I intended, and besides it's not my quote :) Cheers, Brian |
From: Clark C. E. <cc...@cl...> - 2002-09-22 13:11:19
|
On Sat, Sep 21, 2002 at 11:21:47PM -0700, Brian Ingerson wrote: | Python allows tuples and objects to be hash (dictionary) keys and | Ruby supports just about everything as a hash key. Python restricts keys to tuples and objects with a hash() method. Ruby allows just about anything for a key and its hashtable can rehash() Clark |
From: Armin R. <ar...@xs...> - 2002-09-22 08:22:24
|
Wow! A big thanks to all of you! Stefan and I will now include all the comments/corrections. Have a nice WE, =09Armin |