{"id":13509755,"url":"https://github.com/willemdj/erlsom","last_synced_at":"2025-05-14T05:10:23.657Z","repository":{"id":732058,"uuid":"381423","full_name":"willemdj/erlsom","owner":"willemdj","description":"XML parser for Erlang","archived":false,"fork":false,"pushed_at":"2025-03-10T08:12:41.000Z","size":791,"stargazers_count":269,"open_issues_count":10,"forks_count":106,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-14T02:20:39.114Z","etag":null,"topics":["databinder","erlang","sax-parser","xml","xml-schema","xsd"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/willemdj.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2009-11-22T09:20:32.000Z","updated_at":"2025-05-07T15:34:37.000Z","dependencies_parsed_at":"2024-03-01T17:30:10.032Z","dependency_job_id":"80ed4795-077d-49d5-b14a-548bb144ea1a","html_url":"https://github.com/willemdj/erlsom","commit_stats":{"total_commits":124,"total_committers":31,"mean_commits":4.0,"dds":0.5725806451612903,"last_synced_commit":"70cbbf794cec110503811827b035b6efbd90e9ec"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willemdj%2Ferlsom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willemdj%2Ferlsom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willemdj%2Ferlsom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willemdj%2Ferlsom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/willemdj","download_url":"https://codeload.github.com/willemdj/erlsom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254076850,"owners_count":22010611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["databinder","erlang","sax-parser","xml","xml-schema","xsd"],"created_at":"2024-08-01T02:01:12.480Z","updated_at":"2025-05-14T05:10:23.606Z","avatar_url":"https://github.com/willemdj.png","language":"Erlang","funding_links":[],"categories":["XML","XML Tools and Frameworks","Text and Numbers","Tools"],"sub_categories":["In-memory data grids","XML","Mesh networks"],"readme":"# Erlsom #\n\n- [Introduction](#introduction)\n  - [Example XML document](#example)\n- [SAX Mode](#sax)\n  - [SAX Events](#sax_events)\n- [Simple DOM Mode](#DOM)\n- [Data Binder Mode](#binder)\n- [Installation](#installation)\n- [Examples](#examples)\n- [Character encoding](#encoding)\n- [Creation of atoms](#atoms)\n- [Limitations](#limitations)\n  - [XML Schema elements](#elements)\n  - [XML Schema Attributes](#attributes)\n- [Reference](doc/reference.md)\n\n## \u003ca name=\"introduction\"\u003eIntroduction\u003c/a\u003e ##\nErlsom is an Erlang library to parse (and generate) XML documents.\n\nErlsom can be used in a couple of very different modes:\n\n- As a [SAX parser](#sax). This is a [more or less standardized model](\n  http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html) for\n  parsing XML. Every time the parser has processed a meaningful part of the\n  XML document (such as a start tag), it will tell your application about\n  this. The application can process this information (potentially in\n  parallel) while the parser continues to parse the rest of the document.\n  The SAX parser will allow you to efficiently parse XML documents of\n  arbitrary size, but it may take some time to get used to it. If you\n  invest some effort, you may find that it fits very well with the Erlang\n  programming model (personally I have always been very happy about my\n  choice to use a SAX parser as the basis for the rest of Erlsom).\n\n- As a simple sort of [DOM parser](#DOM). Erlsom can translate your XML to\n  the ‘simple form’ that is used by Xmerl. This is a form that is easy to\n  understand, but you have to search your way through the output to get to\n  the information that you need.\n\n- As a [‘data binder’](#binder) Erlsom can translate the XML document to an\n  Erlang data structure that corresponds to an XML Schema. It has the\n  advantage over the SAX parser that it validates the XML document, and\n  that you know exactly what the layout of the output will be. This makes\n  it easy to access the elements that you need in a very direct way. (Look\n  [here](http://www.rpbourret.com/xml/XMLDataBinding.htm) for a general\n  description of XML data binding.)\n\nFor all modes the following applies:\n- If the document is too big to fit into memory, or if the document arrives\n  in some kind of data stream, it can be passed to the parser in blocks of\n  arbitrary size.\n\n- The parser can work directly on binaries. There is no need to transform\n  binaries to lists before passing the data to Erlsom. Using binaries as\n  input has a positive effect on the memory usage and on the speed\n  (provided that you are using Erlang 12B or later - if you are using an\n  older Erlang version the speed will be better if you transform binaries\n  to lists). The binaries can be latin-1, utf-8 or utf-16 encoded.\n\n- The parser has an option to produce output in binary form (only the\n  character data: names of elements and attributes are always strings).\n  This may be convenient if you want to minimize the memory usage, and/or\n  if you need the result in binary format for further processing. Note that it\n  will slow down the parser slightly. If you select this option the encoding of\n  the result will be utf-8 (irrespective of the encoding of the input document).\n\n## \u003ca name=\"example\"\u003eExample XML document\u003c/a\u003e ##\nUnless otherwise indicated, the examples in the next sections will use the following, very simple XML document as input:\n\n```xml\n\u003cfoo attr=\"baz\"\u003e\u003cbar\u003ex\u003c/bar\u003e\u003cbar\u003ey\u003c/bar\u003e\u003c/foo\u003e\n```\n\nThis document is stored in a file called \"minimal.xml\", and read into a\nvariable called Xml by the following commands in the shell:\n\n```\n1\u003e {ok, Xml} = file:read_file(\"minimal.xml\").\n{ok,\u003c\u003c\"\u003cfoo attr=\\\"baz\\\"\u003e\u003cbar\u003ex\u003c/bar\u003e\u003cbar\u003ey\u003c/bar\u003e\u003c/foo\u003e\\r\\n\"\u003e\u003e}\n```\n\nThe following, corresponding XSD (\"minimal.xsd\") is used in the first example for the data binder:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cxsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\u003e\n    \u003cxsd:element name=\"foo\" type=\"foo_type\"/\u003e\n    \u003cxsd:complexType name=\"foo_type\"\u003e\n         \u003cxsd:sequence\u003e\n             \u003cxsd:element name=\"bar\" type=\"xsd:string\"\n             maxOccurs=\"unbounded\"/\u003e\n         \u003c/xsd:sequence\u003e\n         \u003cxsd:attribute name=\"attr\" type=\"xsd:string\"/\u003e\n     \u003c/xsd:complexType\u003e\n\u003c/xsd:schema\u003e\n```\n\n## \u003ca name=\"sax\"\u003eSAX Mode\u003c/a\u003e ##\nThe example below shows how the [example XML](#example) can be processed\nusing the SAX parser:\n\n```\n2\u003e erlsom:parse_sax(Xml, [], fun(Event, Acc) -\u003e io:format(\"~p~n\", [Event]), Acc end).\nstartDocument\n{startElement,[],\"foo\",[],[{attribute,\"attr\",[],[],\"baz\"}]}\n{startElement,[],\"bar\",[],[]}\n{characters,\"x\"}\n{endElement,[],\"bar\",[]}\n{startElement,[],\"bar\",[],[]}\n{characters,\"y\"}\n{endElement,[],\"bar\",[]}\n{endElement,[],\"foo\",[]}\nendDocument\n{ok,[],\"\\r\\n\"}\n```\n\nThe function erlsom:parse_sax takes as its arguments: the XML document, an accumulator value and an ‘event processing function’. This function will process the parts of the XML documents that have been parsed. In this example, this function simply prints these events.\n\nThe next example does something slightly more meaningful: it counts the number of times the \"bar\" element occurs in the XML document. Ok, maybe not very useful, but at least this example will produce a result, not only side effects.\n\n```\n3\u003e CountBar = fun(Event, Acc) -\u003e case Event of {startElement, _, \"bar\", _, _} -\u003e Acc + 1; _ -\u003e Acc end end.\n#Fun\u003cerl_eval.12.113037538\u003e\n\n4\u003e erlsom:parse_sax(Xml, 0, CountBar).\n{ok,2,\"\\r\\n\"}\n```\n\nTo describe it in a rather formal way: `parse_sax(Xml, Acc0, Fun)` calls Fun(Event, AccIn) on successive ‘XML events’ that result from parsing Xml, starting with AccIn == Acc0. Fun/2 must return a new accumulator which is passed to the next call. The function returns {ok, AccOut, Tail}, where AccOut is the final value of the accumulator and Tail the list of characters that follow after the last tag of the XML document. In this example AccOut == 2, since the tag occurs twice.\n(Notice how similar this is to lists:foldl(Fun, Acc0, Sax\\_events), assuming that Sax\\_events is the list of Sax events - I more or less copied this description from the documentation of the lists module.)\n\nIt may still not be very clear to you how this SAX parser can be used to produce useful results. There are some additional examples in the examples directory of the Erlsom distribution. If you are still not convinced you can try to decipher the source code for the ‘data binder’ mode (erlsom_parse.erl) - this was also built on top of the SAX parser.\n\n### \u003ca name=\"sax_events\"\u003eSAX Events\u003c/a\u003e ##\n\n#### startDocument\n\n#### endDocument\nWill NOT be sent out in case of an error\n\n#### {startPrefixMapping, Prefix, URI}\nBegin the scope of a prefix - URI namespace mapping\nWill be sent immediately before the corresponding startElement event.\n\n#### {endPrefixMapping, Prefix}\nEnd the scope of a prefix - URI namespace mapping\nWill be sent immediately before the corresponding endElement event.\n\n#### {startElement, Uri, LocalName, Prefix, [Attributes]}\nThe beginning of an element.\nThere will be a corresponding endElement (even when the element is\nempty).\nAll three name components will be provided.\n\n[Attributes] is a list of attribute records, see sax.hrl.\nNamespace attributes (xmlns:*) will not be reported.\nThere will be NO attribute values for defaulted attributes!\n\nProviding 'Prefix' in stead of 'Qualified name' is probably not quite\nin line with the SAX spec, but it appears to be more convenient.\n\n#### {endElement, Uri, LocalName, Prefix}\nThe end of an element.\n\n#### {characters, Characters}\nCharacter data.\nAll character data will be in one chunk, except if there is a\nCDATA section included inside a character section. In that case\nthere will be separate events for the characters before the CDATA, the\nCDATA section and the characters following it (if any, of course).\n\n#### {ignorableWhitespace, Characters}\nIf a character data section (as it would be reported by the 'characters'\nevent, see above) consists ONLY of whitespace, it will be\nreported as ignorableWhitespace.\n\n#### {processingInstruction, Target, Data}\n\n#### {error, Description}\n\n#### {internalError, Description}\n\n## \u003ca name=\"DOM\"\u003eSimple DOM Mode\u003c/a\u003e ##\nThis mode translates the XML document to a generic data structure. It doesn’t really follow the DOM standard, but in stead it provides a very simple format. In fact, it is very similar to format that is defined as the ‘simple-form’ in the Xmerl documentation.\n\nAn example will probably be sufficient to explain it:\n\n```\nerlsom:simple_form(Xml).\n{ok,{\"foo\",\n     [{\"attr\",\"baz\"}],\n     [{\"bar\",[],[\"x\"]},{\"bar\",[],[\"y\"]}]},\n    \"\\r\\n\"}\n```\n\nResult = {ok, Element, Tail}, where Element = {Tag, Attributes, Content}, Tag is a string (there is an option that allows you to format Tag differently, see the reference section below), Attributes = [{AttributeName, Value}], and Content is a list of Elements and/or strings.\n\n## \u003ca name=\"binder\"\u003eData Binder Mode\u003c/a\u003e ##\nIn this mode, Erlsom parses XML documents that are associated with an XSD (or Schema). It checks whether the XML document conforms to the Schema, and it translates the document to an Erlang structure that is based on the types defined in the Schema. This section tries to explain the relation between the Schema and the Erlang data structure that is produced by Erlsom.\n\nFirst a quick example using the same XML that was used for the other modes. Before we can parse the document we need to ‘compile’ the XML Schema (similar to how you might compile a regular expression).\n\n```\n10\u003e {ok, Model} = erlsom:compile_xsd_file(\"minimal.xsd\").\n{ok,{model,[{typ…\n```\n\nNow you can use this compiled model:\n\n```\n11\u003e {ok, Result, _} = erlsom:scan(Xml, Model).\n{ok,{foo_type,[],\"baz\",[\"x\",\"y\"]},\"\\r\\n\"}\n```\n\nAssuming that you have defined a suitable record #foo\\_type{} (erlsom:write\\_xsd\\_hrl\\_file() can do it for you), you can use in your program (won’t work in the shell):\n\n```\nBarValues = Result#foo_type.bar,\nAttrValue = Result#foo_type.attr,\n```\n\nNice and compact, as you see, but it may need more explanation. I will use a more complex example from the XML Schema  Primer ([XML Schema Part 0: Primer Second Edition](http://www.w3.org/TR/2004/REC-xmlschema-0-20041028/)).\n\n```xml\n\u003cxsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\u003e\n\n  \u003cxsd:annotation\u003e\n    \u003cxsd:documentation xml:lang=\"en\"\u003e\n     Purchase order schema for Example.com.\n     Copyright 2000 Example.com. All rights reserved.\n    \u003c/xsd:documentation\u003e\n  \u003c/xsd:annotation\u003e\n\n  \u003cxsd:element name=\"purchaseOrder\" type=\"PurchaseOrderType\"/\u003e\n\n  \u003cxsd:element name=\"comment\" type=\"xsd:string\"/\u003e\n\n  \u003cxsd:complexType name=\"PurchaseOrderType\"\u003e\n    \u003cxsd:sequence\u003e\n      \u003cxsd:element name=\"shipTo\" type=\"USAddress\"/\u003e\n      \u003cxsd:element name=\"billTo\" type=\"USAddress\"/\u003e\n      \u003cxsd:element ref=\"comment\" minOccurs=\"0\"/\u003e\n      \u003cxsd:element name=\"items\"  type=\"Items\"/\u003e\n    \u003c/xsd:sequence\u003e\n    \u003cxsd:attribute name=\"orderDate\" type=\"xsd:date\"/\u003e\n  \u003c/xsd:complexType\u003e\n\n  \u003cxsd:complexType name=\"USAddress\"\u003e\n    \u003cxsd:sequence\u003e\n      \u003cxsd:element name=\"name\"   type=\"xsd:string\"/\u003e\n      \u003cxsd:element name=\"street\" type=\"xsd:string\"/\u003e\n      \u003cxsd:element name=\"city\"   type=\"xsd:string\"/\u003e\n      \u003cxsd:element name=\"state\"  type=\"xsd:string\"/\u003e\n      \u003cxsd:element name=\"zip\"    type=\"xsd:decimal\"/\u003e\n    \u003c/xsd:sequence\u003e\n    \u003cxsd:attribute name=\"country\" type=\"xsd:NMTOKEN\"\n                   fixed=\"US\"/\u003e\n  \u003c/xsd:complexType\u003e\n\n  \u003cxsd:complexType name=\"Items\"\u003e\n    \u003cxsd:sequence\u003e\n      \u003cxsd:element name=\"item\" minOccurs=\"0\" maxOccurs=\"unbounded\"\u003e\n        \u003cxsd:complexType\u003e\n          \u003cxsd:sequence\u003e\n            \u003cxsd:element name=\"productName\" type=\"xsd:string\"/\u003e\n            \u003cxsd:element name=\"quantity\"\u003e\n              \u003cxsd:simpleType\u003e\n                \u003cxsd:restriction base=\"xsd:positiveInteger\"\u003e\n                  \u003cxsd:maxExclusive value=\"100\"/\u003e\n                \u003c/xsd:restriction\u003e\n              \u003c/xsd:simpleType\u003e\n            \u003c/xsd:element\u003e\n            \u003cxsd:element name=\"USPrice\"  type=\"xsd:decimal\"/\u003e\n            \u003cxsd:element ref=\"comment\"   minOccurs=\"0\"/\u003e\n            \u003cxsd:element name=\"shipDate\" type=\"xsd:date\" minOccurs=\"0\"/\u003e\n          \u003c/xsd:sequence\u003e\n          \u003cxsd:attribute name=\"partNum\" type=\"SKU\" use=\"required\"/\u003e\n        \u003c/xsd:complexType\u003e\n      \u003c/xsd:element\u003e\n    \u003c/xsd:sequence\u003e\n  \u003c/xsd:complexType\u003e\n\n  \u003c!-- Stock Keeping Unit, a code for identifying products --\u003e\n  \u003cxsd:simpleType name=\"SKU\"\u003e\n    \u003cxsd:restriction base=\"xsd:string\"\u003e\n      \u003cxsd:pattern value=\"\\d{3}-[A-Z]{2}\"/\u003e\n    \u003c/xsd:restriction\u003e\n  \u003c/xsd:simpleType\u003e\n\n\u003c/xsd:schema\u003e\n```\n\n*example 1: po.xsd*\n\nThis XSD can be processed by Erlsom: the compiler accepts it, and the parser can parse instances (XML documents) that conform to this schema.\n\nLike the Primer, I will use po.xml as an example XML document.\n\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003cpurchaseOrder orderDate=\"1999-10-20\"\u003e\n   \u003cshipTo country=\"US\"\u003e\n      \u003cname\u003eAlice Smith\u003c/name\u003e\n      \u003cstreet\u003e123 Maple Street\u003c/street\u003e\n      \u003ccity\u003eMill Valley\u003c/city\u003e\n      \u003cstate\u003eCA\u003c/state\u003e\n      \u003czip\u003e90952\u003c/zip\u003e\n   \u003c/shipTo\u003e\n   \u003cbillTo country=\"US\"\u003e\n      \u003cname\u003eRobert Smith\u003c/name\u003e\n      \u003cstreet\u003e8 Oak Avenue\u003c/street\u003e\n      \u003ccity\u003eOld Town\u003c/city\u003e\n      \u003cstate\u003ePA\u003c/state\u003e\n      \u003czip\u003e95819\u003c/zip\u003e\n   \u003c/billTo\u003e\n   \u003ccomment\u003eHurry, my lawn is going wild\u003c!/comment\u003e\n   \u003citems\u003e\n      \u003citem partNum=\"872-AA\"\u003e\n         \u003cproductName\u003eLawnmower\u003c/productName\u003e\n         \u003cquantity\u003e1\u003c/quantity\u003e\n         \u003cUSPrice\u003e148.95\u003c/USPrice\u003e\n         \u003ccomment\u003eConfirm this is electric\u003c/comment\u003e\n      \u003c/item\u003e\n      \u003citem partNum=\"926-AA\"\u003e\n         \u003cproductName\u003eBaby Monitor\u003c/productName\u003e\n         \u003cquantity\u003e1\u003c/quantity\u003e\n         \u003cUSPrice\u003e39.98\u003c/USPrice\u003e\n         \u003cshipDate\u003e1999-05-21\u003c/shipDate\u003e\n      \u003c/item\u003e\n   \u003c/items\u003e\n\u003c/purchaseOrder\u003e\n```\n\n*example 2: po.xml*\n\nTranslating po.xml using erlsom:scan/2 will result in:\n\n```erlang\n{'PurchaseOrderType',[],\n                     \"1999-10-20\",\n                     {'USAddress',[],\n                                  \"US\",\n                                  \"Alice Smith\",\n                                  \"123 Maple Street\",\n                                  \"Mill Valley\",\n                                  \"CA\",\n                                  \"90952\"},\n                     {'USAddress',[],\n                                  \"US\",\n                                  \"Robert Smith\",\n                                  \"8 Oak Avenue\",\n                                  \"Old Town\",\n                                  \"PA\",\n                                  \"95819\"},\n                     \"Hurry, my lawn is going wild!\",\n                     {'Items',[],\n                              [{'Items/item',\n                                     [],\n                                     \"872-AA\",\n                                     \"Lawnmower\",\n                                     \"1\",\n                                     \"148.95\",\n                                     \"Confirm this is electric\",\n                                     undefined},\n                               {'Items/item',\n                                     [],\n                                     \"926-AA\",\n                                     \"Baby Monitor\",\n                                     \"1\",\n                                     \"39.98\",\n                                     undefined,\n                                     \"1999-05-21\"}]}}\n```\n\n*example 3: output for po.xml*\n\nThe output can be interpreted as a structure built from Erlang records. The\ndefinition of these records can either be generated by\nerlsom:write_xsd_hrl_file/3, or you can define them yourself (or a combination:\nyou can run write_xsd_hrl_file and change a few fieldnames and add some\ndefaults). An extract of the .hrl file generated by write_xsd_hrl_file/3:\n\n```erlang\n-record('USAddress', {anyAttribs :: anyAttribs(),\n        country :: string() | undefined,\n        name :: string(),\n        street :: string(),\n        city :: string(),\n        state :: string(),\n        zip :: string()}).\n\n-type 'USAddress'() :: #'USAddress'{}.\n\n\n-record('PurchaseOrderType', {anyAttribs :: anyAttribs(),\n        orderDate :: string() | undefined,\n        shipTo :: 'USAddress'(),\n        billTo :: 'USAddress'(),\n        comment :: string() | undefined,\n        items :: 'Items'()}).\n\n-type 'PurchaseOrderType'() :: #'PurchaseOrderType'{}.\n```\n\n*example 4: record definitions for po.xsd as generated by write_xsd_hrl_file/3*\n\nAs can be seen from the example:\n\n-  attributes are included in the records as the first elements (country,\n   partNum)\n-  elements that are optional (minOccurs=\"0\") for which no value is provided\n   get the value undefined (comment, shipDate).\n-  elements that can occur more than once (maxOccurs \u003e 0 or unbounded) are\n   translated to a list (listOfItem).\n-  every record has ‘anyAttribs’ as its first element. If the Schema allows\n   ‘anyAttributes’, and if these are present in the XML document, then the\n   values will be found here (as a list of attribute-value pairs). Note\n   that this can be avoided by passing the option {include_any_attribs,\n   false} to erlsom:compile_xsd_file: in that case the ‘anyAttribs’ element\n   will not be there.\n\nIt should be noted that there is quite a bit of information in po.xsd that is not used by erlsom:\n\n-  Only in a limited number of situations does erlsom do type checking and\n   translation: only if an element is defined as integer, int, boolean or QName\n   without any further restrictions or extensions. The ‘quantity’ element doesn’t\n   meet these conditions, since (a) it is a positiveInteger, and (b) it is\n   restricted. A value for the quantity element of Ten or -1 would not result in\n   an error or warning, and the string value is not translated to an Erlang\n   integer. This also applies for the user defined simpleTypes, like SKU in the\n   example.\n\n   Note that this  behaviour can be modified by passing the option `{strict,\n   true}` to erlsom:compile_xsd_file: in that case more types will be\n   checked and mapped to Erlang types, for example `float` and `long`. This\n   also applies to `positiveInteger`, but since the limitation that this\n   only works for types without restrictions or extensions still holds, it would not\n   make any difference for the value of ‘quantity’.\n\nIt should be noted that there is quite a bit of information in po.xsd that is not used by erlsom:\n\n-  Only in a limited number of situations does erlsom do type checking and\n   translation: only if an element is defined as integer, int, boolean or QName\n   without any further restrictions or extensions. The ‘quantity’ element doesn’t\n   meet these conditions, since (a) it is a positiveInteger, and (b) it is\n   restricted. A value for the quantity element of Ten or -1 would not result in\n   an error or warning, and the string value is not translated to an Erlang\n   integer. This also applies for the user defined simpleTypes, like SKU in the\n   example.\n-  The fixed attribute is ignored. If there would have been another value than\n   US in po.xml, this would have been accepted without warning or error.\n-  The annotation is ignored (obviously).\n\nIn example 5 a number of additional features is illustrated:\n\n-  elements that belong to a namespace are prefixed in the result. The prefix\n   is determined by a parameter of the function that compiles the XSD.\n-  anonymous types (in the example: spouse) get a name that include the ‘path’,\n   in order to avoid name conflicts.\n-  types (‘records’) are created for choices - the type indicates which\n   alternative was selected (the record b:personType-hobby shows that \"Mowing the lawn\" is a hobby, not a profession).\n\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003cxsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n            targetNamespace=\"http://www.example.org\"\n            xmlns=\"http://www.example.org\"\n            elementFormDefault=\"qualified\"\u003e\n  \u003cxsd:element name=\"person\" type=\"personType\"/\u003e\n  \u003cxsd:complexType name=\"personType\"\u003e\n     \u003cxsd:sequence\u003e\n       \u003c!-- an element with an attribute --\u003e\n       \u003cxsd:element name = \"id\"\u003e\n         \u003cxsd:complexType\u003e\n           \u003cxsd:simpleContent\u003e\n             \u003cxsd:extension base = \"xsd:string\"\u003e\n               \u003cxsd:attribute name = \"type\" type = \"xsd:string\"/\u003e\n               \u003c!-- allow other attributes--\u003e\n               \u003cxsd:anyAttribute namespace=\"##other\"/\u003e\n             \u003c/xsd:extension\u003e\n           \u003c/xsd:simpleContent\u003e\n         \u003c/xsd:complexType\u003e\n       \u003c/xsd:element\u003e\n\n       \u003c!-- choice --\u003e\n       \u003cxsd:choice\u003e\n         \u003cxsd:element name=\"profession\" type=\"xsd:string\"/\u003e\n         \u003cxsd:element name=\"hobby\" type=\"xsd:string\"/\u003e\n       \u003c/xsd:choice\u003e\n\n       \u003c!-- group --\u003e\n       \u003cxsd:group  ref=\"name\"/\u003e\n\n       \u003c!-- local type --\u003e\n       \u003cxsd:element name=\"spouse\" xsi:nillable=\"true\"\u003e\n         \u003cxsd:complexType\u003e\n           \u003cxsd:sequence\u003e\n             \u003cxsd:element  name=\"name\" type=\"xsd:string\"/\u003e\n             \u003cxsd:element  name=\"age\" type=\"xsd:string\"/\u003e\n           \u003c/xsd:sequence\u003e\n         \u003c/xsd:complexType\u003e\n       \u003c/xsd:element\u003e\n\n    \u003c/xsd:sequence\u003e\n  \u003c/xsd:complexType\u003e\n\n  \u003cxsd:group name=\"name\"\u003e\n    \u003cxsd:sequence\u003e\n      \u003c!-- nillable element --\u003e\n      \u003cxsd:element name=\"firstName\"\n                   type=\"xsd:string\" nillable=\"true\"/\u003e\n      \u003cxsd:element name=\"lastName\" type=\"xsd:string\"/\u003e\n    \u003c/xsd:sequence\u003e\n  \u003c/xsd:group\u003e\n\n\u003c/xsd:schema\u003e\n```\n\n*example 5: misc.xsd: namespace, choice, group*\n\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003cperson xmlns=\"http://www.example.org\"\u003e\n  \u003cid type=\"passport\"\u003e123\u003c/id\u003e\n  \u003chobby\u003emowing the lawn\u003c/hobby\u003e\n  \u003cfirstName\u003eJan\u003c/firstName\u003e\n  \u003clastName\u003ePietersen\u003c/lastName\u003e\n  \u003cspouse\u003e\n      \u003cname\u003eJet Pietersen\u003c/name\u003e\n      \u003cage\u003e33\u003c/age\u003e\n  \u003c/spouse\u003e\n\u003c/person\u003e\n```\n\n*example 6: misc.xml*\n\nThe XSD can be compiled by the command\n\n```\n\u003e {ok, Model} = erlsom:compile_xsd_file(\"misc.xsd\",\n                                        [{prefix, \"b\"}]).\n```\n\nAfter that the XML can be parsed using the command\n\n```\n\u003e {ok, Out, Rest} = erlsom:scan_file(\"misc_example.xml\", Model).\n```\n\nOut is the output shown below, and Rest is a string of the characters that may follow after the end tag of the XML.\n\n```erlang\n{'b:personType',[],\n                {'b:personType/id',[], \"passport\",\"123\"},\n                {'b:personType-hobby',[], \"mowing the lawn\"},\n                {'b:name',[], \"Jan\",\"Pietersen\"},\n                {'b:personType/spouse',[], \"Jet Pietersen\",\"33\"}}\n```\n\n*example 7: output for misc.xml*\n\nTo show some additional features, have a look at the result of parsing misc_2.xml.\n\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003cperson xmlns=\"http://www.example.org\"\n        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n        xmlns:passport=\"some_uri\"\u003e\n  \u003cid type=\"passport\" passport:issued=\"2011\"\u003e123\u003c/id\u003e\n  \u003chobby\u003emowing the lawn\u003c/hobby\u003e\n  \u003cfirstName xsi:nil=\"true\"/\u003e\n  \u003clastName\u003ePietersen\u003c/lastName\u003e\n  \u003cspouse xsi:nil=\"true\"\u003e\u003c/spouse\u003e\n\u003c/person\u003e\n```\n\n*example 8: misc_2.xml*\n\n```erlang\n{'b:personType',\n   [],\n   {'b:personType/id',\n     [{{\"issued\",\"some_uri\"},\"2011\"}],\"passport\",\"123\"},\n      {'b:personType-hobby',[],\"mowing the lawn\"},\n      {'b:name',[],nil,\"Pietersen\"},\n      {nil,{'b:personType/spouse',\n            [{{\"nil\",\"http://www.w3.org/2001/XMLSchema-instance\"},\n              \"true\"}],\n            undefined,\n            undefined}}}\n```\n\n*example 9: output for misc_2.xml*\n\nIt shows how \"nil\" values are represented - note that there are 2 different cases: for a simple type the value `nil` is used, but for a complex type `{nil, Record}` is used, where Record is a record of the same type that would be used if a non-nil value would have been provided. The reason for this slightly awkward pattern is that a nil-value may still have attributes.\n\nExample 9 also shows what happens to \"any-attributes\" (\"issued\", in this case): these are put into the first field of the record.\n\n*A note about schema inclusion*\n\nBe careful when working with complex schemas since Erlsom does not handle duplicate inclusions. You may end up with duplicate types!\n\nHowever, duplicate inclusions can be resolved, e.g. by either editing the schemas or by detecting duplicate includes in a custom `include_fun` (which should then return an empty schema).\n\n## \u003ca name=\"installation\"\u003eInstallation\u003c/a\u003e\nThe easiest way to install Erlsom is probably to use rebar.\n\nKlacke (Claes Wickstrom) has provided a makefile. This should enable Unix users to install Erlsom easily.\n\nAnyway,  even for Windows users and without rebar, installing erlsom should be straightforward. One way to do it is described below.\n\n- Put all the files into the directory `ROOT/lib/erlsom-1.2.1/src`, where ROOT\n  is the directory that contains Erlang (C:\\Program Files\\erl5.6.1 on my Windows system).\n- Start the Erlang shell\n- Change the working directory to `ROOT/lib/erlsom-1.2.1/src`:\n\n```\n1\u003e cd('../lib/erlsom-1.2.1/src').\nC:/Program Files/erl5.6.1/lib/erlsom-1.2.1/src\nok\n```\n\n- Compile the source files:\n\n```\n2\u003e c(\"erlsom\"),\nc(\"erlsom_parse\"),\nc(\"erlsom_lib\"),\nc(\"erlsom_compile\"),\nc(\"erlsom_write\"),\nc(\"erlsom_parseXsd\"),\nc(\"erlsom_sax\"),\nc(\"erlsom_pass2\"),\nc(\"erlsom_writeHrl\"),\nc(\"erlsom_add\"),\nc(\"erlsom_ucs\"),\nc(\"erlsom_sax_utf8\"),\nc(\"erlsom_sax_latin1\"),\nc(\"erlsom_sax_latin9\"),\nc(\"erlsom_sax_utf16be\"),\nc(\"erlsom_sax_utf16le\"),\nc(\"erlsom_sax_list\"),\nc(\"erlsom_sax_lib\"),\nc(\"erlsom_simple_form\").\n```\n\n- Move the .beam files to `ROOT/lib/erlsom-1.2.1/ebin`.\n\n- Alternatively you can use emake for the last 2 steps:\n\n```\n2\u003e make:all([{outdir, \"../ebin\"}]).\n```\n\n\n## \u003ca name=\"examples\"\u003eExamples\u003c/a\u003e ##\nThe distribution includes 7 examples:\n\n-  erlsom_example: this shows the use of the basic functions to compile an XSD,\n   to parse an XML document and to write an XML document.\n\n   To run the example from the Erlang shell: cd to the directory that contains the\n   code (something like `cd('lib/erlsom-1.2.1/examples/erlsom_example').`),\n   compile (`c(\"erlsom_example\").`) and run (`erlsom_example:run().`).\n\n- erlsom\\_sax\\_example: this shows the features of the SAX parser.\n\n- example1: this example has 2 purposes:\n   - It shows how easy Erlsom makes it for you to use an XML configuration\n     file. The configuration file describes a set of 10 test cases, which are\n     run by this example. The configuration file is described by \"example1.xsd\".\n     Compiling this XSD and then parsing the configuration file (\"example1.xml\")\n     gives you access to an Erlang structure of records that corresponds with the\n     XML schema.\n\n   - It shows how 11 different schemas (names \"abb1.xsd\" through \"abb11.xsd\")\n     can describe the same XML document (named \"abb.xml\"), and it shows the output\n     that results from running Erlsom on this file using these schema’s.\n     To run the example for XSD abb1.xsd, use the command `example1:test_erlsom(\"abb1\").`\n\n- soap\\_example: this shows how to use the `erlsom:add_xsd_file()` function,\n  and it gives an example how you might parse and generate SOAP messages.\n\n- continuation: this shows how to use the sax parser with a\n  ‘continuation-function’. This can be used for parsing of very big files or\n  streams. The continuation function should return a block of data; this will be\n  parsed (calling the sax callback function when appropriate) and after that the\n  function is called again to get the next block of data. The example shows how a\n  file of arbitrary size can be parsed. The comments in the code should help you\n  to understand and use this function.\n\n- complex\\_form: shows how you could create a back-end to the sax parser that\n  produces the same output as Xmerl, and how you could then use the Xpath\n  functions that Xmerl provides.\n\n- book\\_store; actually three examples, demonstrating the three modes that\n  erlsom supports. The third example shows how you might combine different modes within\n  a function that scans a file.\n\n## \u003ca name=\"encoding\"\u003eCharacter encoding\u003c/a\u003e\nThe sax parser accepts binaries as input. It will recognize UTF-8 and UTF-16 encoding by looking at the byte order mark and the first character of the document. Additionally ISO-8859-1 and ISO-8859-15 encoding is recognized if this is indicated by the XML declaration. If the XML declaration specifies another character set, an error will be thrown. It should not be very difficult to add support for other character sets, however.\n\nAs specified by the XML standard, the default encoding is UTF-8. If the first byte of the document is a ‘\u0026lt;’ ASCII character and if the XML declaration does not specify anything else, it will be assumed that the encoding is UTF-8.\n\nThe result of erlsom:write is a list of Unicode code points. Normally this will have to be encoded before it can be used. The function erlsom\\_ucs:to\\_utf8/1 can be used to do this.\n\n## \u003ca name=\"atoms\"\u003eCreation of atoms\u003c/a\u003e\nEspecially in the context of internet applications, it may be a problem if new atoms are created as a result of communication based on XML (SOAP, XML-RPC, AJAX). The number of atoms that can be created within the Erlang runtime environment is limited, and uncontrolled creation of atoms may cause the system to crash.\n\nErlsom:scan/2 does not create new atoms. It uses string\\_to\\_existing\\_atom to create the atoms that are used in the records.\n\nErlsom:compile\\_xsd does create atoms. However, usually this function won’t be called with arbitrary end user input as its argument, so normally this should not be a problem.\n\n## \u003ca name=\"limitations\"\u003eLimitations\u003c/a\u003e\nSome checks/validity constraints are accepted in the XSD, but not enforced during parsing:\n\n- all simple types are interpreted as string. This applies to the built in\n  types (float, positiveInteger, gYear etc), and also to types that are\n  restricted (using 'facets') or extended (for example 'union' types). The only\n  exceptions are Integer, Boolean and QName, these are translated.\n\n  If the option `{strict, true}` is used when compiling the XSD, a number\n  of additional types will be translated (and checked): Float, Double and\n  all types that are derived from the Integer type, such as\n  positiveInteger, nonNegativeInteger, Long, unsignedLong etc.\n\n- Key, Unique etc. are not supported - if these elements occur in the XSD, they\n  are simply ignored.\n\nThe SAX parser has the following limitations:\n\n- It doesn’t support external entities.\n- It doesn’t do any validation: if the XML includes a DTD, this is simply\n  ignored.\n\nThe data binder has the following additional limitation:\n\n- Names of elements and attributes cannot contain characters outside the Erlang\n  character set (because they are translated to atoms).\n\n### \u003ca name=\"elements\"\u003eXML Schema elements\u003c/a\u003e\n\u003ctable width=\"100%\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\"\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eAll\u003c/td\u003e\u003ctd\u003eSupported. The parser puts the elements into the resulting record in a fixed place (independent of the order in which they are received).\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eAnnotation\u003c/td\u003e\u003ctd\u003eIgnored (anything enclosed in \u003cdocumentation\u003e\u003c/documentation\u003e is ignored).\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eAny\u003c/td\u003e\u003ctd\u003eSupported. However, only elements that are included in the model will show up in the result. Elements are part of the model if they are included in the XSD that was compiled, or if they have been added using erlsom:add_file().\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eanyAttribute\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eAppinfo\u003c/td\u003e\u003ctd\u003eIgnored (anything enclosed in \u003cdocumentation\u003e\u003c/documentation\u003e is ignored. \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eAttribute\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eattributeGroup\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eChoice\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003ecomplexContent\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003ecomplexType\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eDocumentation\u003c/td\u003e\u003ctd\u003eAccepted, but ignored. Anything enclosed in \u003ccode\u003e\u003cdocumentation\u003e\u003c/documentation\u003e\u003c/code\u003e is ignored (as long as it is valid XML).\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eElement\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eEnumeration\u003c/td\u003e\u003ctd\u003eIgnored (all restrictions on simple types are ignored - those types are treated as ‘string’)\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eExtension\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eField\u003c/td\u003e\u003ctd\u003eIgnored (anything enclosed in \u003ccode\u003e\u003cunique\u003e\u003c/unique\u003e\u003c/code\u003e is ignored).\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eGroup\u003c/td\u003e\u003ctd\u003eSupported.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eImport\u003c/td\u003e\u003ctd\u003eSupported. However, the support for finding the imported files is limited. See (and modify, if necessary...) the function findFile in erlsom_lib.erl. \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eInclude\u003c/td\u003e\u003ctd\u003eSupported. However, the support for finding the included files is limited. See (and modify, if necessary...) the function findFile in erlsom_lib.erl.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eKey\u003c/td\u003e\u003ctd\u003eIgnored.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eKeyref\u003c/td\u003e\u003ctd\u003eIgnored\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eLength\u003c/td\u003e\u003ctd\u003eIgnored (all restrictions on simple types are ignored - those types are treated as ‘string’)\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eList\u003c/td\u003e\u003ctd\u003eIgnored (all restrictions on simple types are ignored - those types are treated as ‘string’)\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003emaxInclusive\u003c/td\u003e\u003ctd\u003e(all restrictions on simple types are ignored - those types are treated as ‘string’)\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003emaxLength\u003c/td\u003e\u003ctd\u003e(see maxInclusive) \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eminInclusive\u003c/td\u003e\u003ctd\u003e(see maxInclusive) \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eminLength\u003c/td\u003e\u003ctd\u003e(see maxInclusive) \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003ePattern\u003c/td\u003e\u003ctd\u003e(see maxInclusive) \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eRedefine\u003c/td\u003e\u003ctd\u003eSupported. However, the support for finding the imported files is limited. See (and modify, if necessary...) the function findFile in erlsom_lib.erl.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eRestriction\u003c/td\u003e\u003ctd\u003eSupported as a way to create a derived complex type (but it is not checked whether this is really a restriction of the base type). Ignored on simpleTypes (all restrictions on simple types are ignored - those types are treated as ‘string’)\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eSchema\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eSelector\u003c/td\u003e\u003ctd\u003eIgnored (anything enclosed in \u003ccode\u003e\u003cunique\u003e\u003c/unique\u003e\u003c/code\u003e is ignored).\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eSequence\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003esimpleContent\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003esimpleType\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eUnion\u003c/td\u003e\u003ctd\u003eIgnored (all restrictions on simple types are ignored - those types are treated as ‘string’)\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eUnique\u003c/td\u003e\u003ctd\u003eIgnored\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n### \u003ca name=\"attributes\"\u003eXML Schema Attributes\u003c/a\u003e\n\n\u003ctable width=\"100%\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\"\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eAbstract\u003c/td\u003e\u003ctd\u003eignored. As a consequence, the parser may accept documents that contain instances of abstract types.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eattributeFormDefault\u003c/td\u003e\u003ctd\u003eSupported.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eBlock\u003c/td\u003e\u003ctd\u003enot supported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eblockDefault\u003c/td\u003e\u003ctd\u003eignored \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eDefault\u003c/td\u003e\u003ctd\u003eignored (note that this not just a check that is not performed: the default value will not be provided)\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eFinal\u003c/td\u003e\u003ctd\u003eIgnored\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003efinalDefault\u003c/td\u003e\u003ctd\u003eIgnored\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eFixed\u003c/td\u003e\u003ctd\u003eIgnored\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eForm\u003c/td\u003e\u003ctd\u003enot supported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eMixed\u003c/td\u003e\u003ctd\u003eSupported (text values are inserted into a list of values) \u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eminOccurs, maxOccurs\u003c/td\u003e\u003ctd\u003esupported, except on group definitions\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003enamespace (for 'any')\u003c/td\u003e\u003ctd\u003esupported, but lists of values are not supported (##any, ##local and ##other are supported). A list of values is treated as '##any'.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eschemaLocation\u003c/td\u003e\u003ctd\u003esupported in a limited way, see 'import'.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003exsi:schemaLocation\u003c/td\u003e\u003ctd\u003eIgnored\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003esubstitutionGroup\u003c/td\u003e\u003ctd\u003eSupported\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eType\u003c/td\u003e\u003ctd\u003esupported, but there is no check on the built-in types, except for integer, int, boolean and QName.\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd valign=\"top\"\u003eUse\u003c/td\u003e\u003ctd\u003esupported, but 'prohibited' is ignored (treated as 'optional').\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n## Reference ##\nSee [Reference](doc/reference.md).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillemdj%2Ferlsom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwillemdj%2Ferlsom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillemdj%2Ferlsom/lists"}