14 ms·
Erik Naggum on Attributes in SGML, XML, Lisp (2001)
- kjhughes 11y agoI've been immersed in the markup world since the SGML days, and even I prefer s-expressions to SGML/XML. But here's the thing: XML is all about agreement. The value is not found at the syntactic level, where needless irregularities exit. The value is that more than a critical mass of agreement formed, and this agreement allowed the development of tools and standards useful across industries. Moreover, the low-level agreement on XML has enabled higher level agreement on vocabularies and grammars in many disparate sectors. Sure, if you had a clean slate you could improve many parts of the XML standards. Consider, for example, XML Schema (XSD). The irregularities and complexity there are similarly annoying. I'd much rather write RELAX schemas. However, whole sectors have selected XML Schema and developed vocabularies and grammars whose value isn't found at the syntactical level; it's found in the agreement reflected in the decisions over vocabulary and grammar made by disparate groups striving to develop a common exchange mechanism. Quibbles over syntax miss XML's real merit: XML enables agreement in developing vocabularies and grammars. Apropos: Here's my Stack Overflow answer to the question of when to use XML attributes vs elements, written in XML for fun: http://stackoverflow.com/a/23133755/290085 http://stackoverflow.com/a/23133755/290085
- tel 11y agoI don't mind the syntax and suppose I agree that consensus syntax is the right syntax. The problem is beneath that: XML's semantics are tremendously large while also being a complete mess. The upshot is that the difficulty of being a compliant adopter---of matching such a large, nebulous, incompletely defined set of inconsistencies---is tremendous and instead there are leagues of partial, massively inconsistent consumers and producers who hammer out successful communication via a list of patches. To some degree this situation was inevitable, but XML exacerbates it and cements the pattern.
- kjhughes 11y agoSemantics has two senses that could apply here. In one sense, XML itself is semantically neutral. The association between elements/attributes names and real world objects is merely suggestive. In another sense (that of semantic analysis found in compiler design), validating XML parsers could be said to be enforcing semantics expressed in schemas. I suppose it is in this sense that your objection applies. In the case of XML Schemas or DTDs, I would have to agree. You might find RELAX NG to be less of a semantic mess given its basis in finite tree automata.
- tel 11y agoA majority of my concerns were resting on XML Schemas and the like—or even OWL (!)—but even recognizing what you mean about XML being semantically neutral it's still... semantically dangerous. The issue at hand where attributes and elements can serve very similar purpose is a great example. In a technical sense XML does not suggest anything about the relative meaning of these two bits, but with near universal acclaim they're used as "metadata" and "child data" whatever the speaker might believe those to mean. In spiritually embracing TIMTOWTDI, XML has created a playing field where semantics are by default ambiguous and have to fight their way out of that disadvantage. In some sense, XML-without-semantics has too much structure and this creates a minefield for laying meaning atop it.
- chriswarbo 11y agoSome other comparisons of XML and s-expressions: http://okmij.org/ftp/Scheme/xml.html http://okmij.org/ftp/Scheme/xml.html http://homepages.inf.ed.ac.uk/wadler/papers/xml-essence/xml-essence.pdf http://homepages.inf.ed.ac.uk/wadler/papers/xml-essence/xml-... A choice quote from the latter: > So the essence of XML is this: the problem it solves is not hard, and it does not solve the problem well.
- cm3 11y agoI wish there we had an S-Expressions based alternative to Docbook for writing manuals and books. You can argue that DSSSL should have been preferred over XSL and friends but people seem to like verbosity even if the alternative (S-Expressions) is as precise and unambiguous.
- brudgers 11y agoMathew Flatt's Scribble might be in that ballpark I think. http://docs.racket-lang.org/scribble/index.html?q=dot http://docs.racket-lang.org/scribble/index.html?q=dot
- pjmlp 11y agoBack when we were writing documentation in Docbook we just used a GUI editor like oXygen , so it did not matter.
- outworlder 11y agoNot a pure S-Expression based (it defines its own language), but it is intended for writing books: http://pkg-build.racket-lang.org/doc/pollen/ http://pkg-build.racket-lang.org/doc/pollen/ practicaltypography.com was made with it.
- otabdeveloper1 11y agoSomeone's been confusing syntax and internal representation again. Simple: parse <foo bar="zot">quux</foo> as (JSON-like) { "foo": { "bar" : "zot", "" : "quux" } } Problem solved, XML is now logical again.
- ICWiener 11y agoSlow clap
- networked 11y agoThere is an existing alternative syntax for XML data [1] that represents it as a list of key-value pairs where the keys are XPath-like paths. In this syntax <foo bar="zot">quux</foo> would be represented as /foo/@bar=zot /foo=quux I think data serialization formats of this particular kind are underused. They are dead simple to parse while still being reasonably human-friendly (more so than XML, I'd say). Get rid of the attributes and introduce the convention that nodes with children named "0", "1", ... , "$N" are arrays and you can represent JSON. [1] http://www.ofb.net/~egnor/xml2/ http://www.ofb.net/~egnor/xml2/
- smrtinsert 11y agoI like this, I had an instinct about making a file format similar to this, except pushing the path onto a stack. <foo bar="zot"><baz>quux</baz></foo> [foo] @bar="zoot" [baz] "quux" [] [] I figured you would save a little in the serialization. In practice I rarely need such a thing, and just serialize a structure to whatever I'm working with (s expressions, or in java xstream etc since those xml files are read somewhere...)
- magnusjonsson 11y agoThis does not do away the distinction between attributes and content -- that attributes are flat strings while content can be nested.
- kmill 11y agoWhen you say that someone's been confusing syntax and internal representation, are you speaking of yourself? You don't parse XML as JSON, though you might parse XML and serialize the resulting internal representation as JSON. Also, XML is the syntactic representation of the document model, so your JSON isn't XML because it's a different sequence of characters. That said, the JSON representation has a bug: what if there are multiple child elements? A fix would be using numeric indices for the children rather than the empty string. Then it would look both like an object with keys (attributes) and an array (of elements). Though, if you want to serialize that back into XML, you would need to make sure you never use non-strings as attribute values! Another bug is that the objects don't maintain their tag name; writing code to process data in this representation would be fairly annoying because a pointer to an element would be an object plus a key, rather than just an object. A fix for this would be to have a "tag" key inside the object.
- thomasfl 11y agoI get terrible deja vu moments when I read Naggum's postings on the net. I knew him as a fellow student, long before I heard about his rants on the net and he actually had a very soft voice and spoke very calmly. Later I had the opprtunity to work with him professionally as well. He was a pleasure to have in meetings away from keyboard, but group discussions by e-mail could be very unpleasant.
- wglb 11y agoTim Bray said pretty much the same thing: https://www.tbray.org/ongoing/When/200x/2009/06/20/Erik-Naggum https://www.tbray.org/ongoing/When/200x/2009/06/20/Erik-Nagg...
- jerf 11y agoThat's actually why I like XML... the two-dimensional distinction between "metadata" and "content" can be really helpful... if and only if you need it. If you need it, then you are dealing with a fundamentally complicated format, and you will actually experience more pain trying to jam it into a single-dimensional format like JSON. By contrast, if the relevant data does not need the two dimensions, which is true of most things, XML is a terrible choice; left adrift without a meaningful way to distinguish between what should be "attribute" and what should be "content", both in theory and in practice all the choices turn out to be terrible. And, again, if you really need it, the available third dimension provided by XML namespacing is a life-saver when you need it, and incredibly redundant when you don't. I often dislike the phrase "Use the right tool for the job", because it is vacuous when not tied to some sort of suggestion on how you should determine what the right tool is, so: Match the dimensionality of your data to the dimensionality of the serialization format. The vast bulk of stuff you will encounter day-to-day is one dimensional and fits in JSON or a friend just fine. Use that. A nontrivial quantity of things fits into XML, mostly delimited text; use XML then. Every once in a while you need modularity in your XML format... do not reinvent XML namespaces, use them. (This is mostly for BIG standards, like XMPP or XHTML.) Use neither more nor less than what you need.
- adwf 11y agoThis reminds me of one of my biggest facepalm-ing moments when I first started using Lisp. I needed to serialise some data to disk, it was all in a list form - (list (a b) (c d)) kinda thing. So I thought to use XML format to store it on disk as that's what I had experience with in other languages. I was about halfway through writing the (write-to-xml) function when I realised I could just write the entire lisp expression to the file instead... Not only was it smaller, it had the huge advantage of not needing to parse it back when I wanted to read from disk, I just called the inbuilt (read) function. Thankfully I only wasted an afternoon! That's what really ingrained the whole "data is code, code is data" idea into me. I even went on to write the structure function to each file as well, so that no matter what I did to the data structure down the line, I would still have the actual code needed to understand it. Right next to the data itself. Not only was my code self-documenting, my data was as well ;)
- wodenokoto 11y agoWhy does everybody say it's lisp thing to save an expression to disc, or that "code is data in lisp" kind of things? Every language I've ever used has variable assignment and you can write those to a document and execute it.
- latiera 11y agoBecause code is data is code in lisp. That's not the case in C or Java or C# or Rust or whatever.
- lisper 11y agoI have never understood Erik's enduring appeal, particularly in light of the vehemence with which he could be technically wrong. <foo bar="zot">quux</foo> should be read as (foo (bar "zot") "quux") and most definitely _NOT_ as ((:foo :bar "zot") "quux") Erik has this exactly backwards. His rendering is ambiguous: it does not distinguish <foo bar="zot"/> from <foo><bar>zot</bar></foo> (as he himself implicitly acknowledges later in the post). Also, rendering unqualified tags as keywords makes it easier to deal with namespaces. IMHO the Right Way to render <foo bar="zot">quux</foo> is ((:foo :bar "zot") "quux") with the further qualification that if there are no tags then ((:foo) "quux") can be simplfied to (:foo "quux"). This preserves a 1-1 correspondence between XML and sexprs, which is IMHO a requirement (in fact, the only requirement) for a reasonable mapping. If you have a 1-1 correspondence then you can freely convert back and forth between the two. If you don't, then you can't.
- Quanttek 11y ago> IMHO the Right Way to render <foo bar="zot">quux</foo> is ((:foo :bar "zot") "quux") with the further qualification that if there are no tags then ((:foo) "quux") can be simplfied to (:foo "quux"). Alternatively you could also write (foo ((bar "zot)) quux) as it is handled in Racket's X-expressions, which has the distinct advantage that the symbol/identifier foo is not nested one level deeper, which makes reading it harder, while still preserving the 1-1 correspondence. Though in this case the meta-information is the first argument instead of being part of the identifier. It also works perfectly with stuff like <foo bar="zot" baz="zor">quux</foo>, which is read as (foo ((bar zot) (baz zor)) quux). I personally think this is way better than ((:foo :bar "zot" :baz "zor) "quux")
- lisper 11y ago> which has the distinct advantage that the symbol/identifier foo is not nested one level deeper Why is that an advantage? I actually like the aesthetics of the extra parens in the CAR. It provides a clear visual distinction between code and markup (at least in Common Lisp, where ((...) ...) is defined by the standard to be a syntax error) which I think is a feature. e.g.: ((:div :class "toplevel" :style "display:block") (:h1 "This is a heading") "This is content") I think it looks kinda nice.
- yarrel 11y agoWhere did he copy and misunderstand this from?
- cust_support 11y agoI'm not even sure why we're discussing this when the post is mostly a strawman. There isn't any example given for "what makes it so goddamn hard to reason about SGML documents". If I understand the idea, he is suggesting that <foo bar="zot">quux</foo> is the same as <foo bar="zot" text="quux"/> or <foo><bar>zot</bar>quux</foo> The ambiguity is introduced when you suggest that meta-information and information are the same thing. Clearly, we wouldn't say that context is the same as experience or that memory is the same as reality. Meta-information and information can be used in different ways to express or define the document which is why it would be better to understand the original complaint. The syntax exists because the distinction is useful for simple things like separating style from content (as others have mentioned). When there is ambiguity about the nature or value of the meta-information, it has nothing to do with the syntax. For example: <apply> <in/> <cn type="complex-cartesian">17<sep/>29</cn> <complexes/> </apply> does a pretty poor job of conveying the information and the distinction between the element "complexes" and the attribute "type" is not readily understood. But let's not throw out the baby with the bathwater and suggest that the distinction is stupid when clearly the universe presented you with an absurdity.
- breck 11y agoThe LISP code there doesn't make things clearer IMO but I agree completely with his point that the attribute and content rules add huge unneeded complexity to XML. Really enjoy these types of articles on markup languages. If there are any other markup language nerds out there I've been chipping away at a simple one (https://github.com/breck7/space https://github.com/breck7/space), and would love feedback. And if you have one as well always love looking at different ideas.