{"id":22685962,"url":"https://github.com/rpgoldman/xmls","last_synced_at":"2026-01-07T09:06:08.703Z","repository":{"id":37794619,"uuid":"240159683","full_name":"rpgoldman/xmls","owner":"rpgoldman","description":"Simple, lightweight XML library for Common Lisp","archived":false,"fork":false,"pushed_at":"2024-02-27T17:37:50.000Z","size":205,"stargazers_count":20,"open_issues_count":4,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T11:51:06.036Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rpgoldman.png","metadata":{"files":{"readme":"README.html","changelog":"Changelog","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}},"created_at":"2020-02-13T02:24:30.000Z","updated_at":"2024-10-21T21:09:34.000Z","dependencies_parsed_at":"2024-01-05T22:14:30.821Z","dependency_job_id":"f4d5070d-ab79-4b08-b006-f005d0b05dcd","html_url":"https://github.com/rpgoldman/xmls","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpgoldman%2Fxmls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpgoldman%2Fxmls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpgoldman%2Fxmls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpgoldman%2Fxmls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rpgoldman","download_url":"https://codeload.github.com/rpgoldman/xmls/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246202220,"owners_count":20739912,"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":[],"created_at":"2024-12-09T22:25:10.050Z","updated_at":"2026-01-07T09:06:08.670Z","avatar_url":"https://github.com/rpgoldman.png","language":"Common Lisp","readme":"\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003ctitle\u003eXMLS: Common Lisp XML Parser\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003ch1\u003eXMLS\u003c/h1\u003e\n\u003ccenter\u003eManual For Version 3\u003c/center\u003e\n\n\u003ch2\u003eSummary\u003c/h2\u003e\n\u003cp\u003e\n  Xmls is a small, simple, non-validating xml parser for Common Lisp.  It's\n  designed to be a self-contained, easily embedded parser that recognizes a useful\n  subset of the XML spec.  It provides a simple mapping from xml to lisp \n  structures or s-expressions and back.\n\u003c/p\u003e\n\u003cp\u003eSince XMLS was first released it has gained some additional\ncomplications/features.  In particular:\u003c/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003cstrong\u003eNow XMLS by default parses XML documents into lisp structures,\n  rather than s-expressions.\u003c/strong\u003e  This makes accessing the structures\n  simpler and more reliable. See \u003ca href=\"#Compatibility\" \u003esection on backward compatibility\u003c/a\u003e.\u003c/li\u003e\n  \u003cli\u003eWe have added clearly named accessors to further improve\n  extraction of information from parsed XML.\u003c/li\u003e\n  \u003cli\u003eThanks to Max Rottenkolber, we now have the affiliated library,\n  \u003ca href=\"#octets\"\u003e\u003ccode\u003exmls/octets\u003c/code\u003e\u003c/a\u003e that will open streams for the XMLS parser,\n  processing any content-type declarations in the process.\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003ch2\u003eFeatures\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\n    Free (BSD license).\n  \u003c/li\u003e\n  \u003cli\u003e\n    Understands enough of the xml spec to parse many common documents, including\n    those occurring in common internet protocols like xml-rpc, webdav, and BEEP.\n    Parses 85 out of the 98 valid documents in the oasis parser compliance suite.\n  \u003c/li\u003e\n  \u003cli\u003e\n    Small and easily embedded.  The entire parser is contained in one\n    file and it's currently less than 600 lines of code.  Xmls is written in\n    pure lisp and requires no external parsing tools or foreign libraries.\n  \u003c/li\u003e\n  \u003cli\u003e\n    Supports xml namespaces.\n  \u003c/li\u003e\n  \u003cli\u003e\n    Threadsafe.\n  \u003c/li\u003e\n  \u003cli\u003e\n    Serializes s-expr list structures back to xml as well as parsing xml.\n  \u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003eLimitations\u003c/h2\u003e\n\u003cul\u003e\n  \u003cli\u003e\n    Parses entire document into memory and consequently can't handle large\n    documents.\n  \u003c/li\u003e\n  \u003cli\u003e\n    No detailed error reporting.\n  \u003c/li\u003e\n  \u003cli\u003e\n  Hand-built LR parser, meaning the parser structure is a little hard\n  to understand, and can be hard to modify.  Use of CL-YACC or similar\n  might be a preferable route for a rewrite.\n  \u003c/li\u003e\n\u003c/ul\u003e\n\n\u003ch2\u003eXML Representation\u003c/h2\u003e\n\n\u003cp\u003e\n  Parsed xml is represented as a nested lisp structure, unlike in the\n  original version, where it was a lisp list.  The s-expression\n  representation is still maintained, and there are \u003ca href=\"#translators\"\u003efunctions to\n  translate to and from this notation\u003c/a\u003e. \n\u003c/p\u003e\n\n\u003ch3\u003eXML representation as lisp structures\u003c/h3\u003e\n\n\u003cp\u003eIn the structure representation, a node, corresponding to an XML\nelement, is defined as follows:\n\u003c/p\u003e\n\n\u003cpre\u003e(defstruct (node (:constructor %make-node))\n  name\n  ns\n  attrs\n  children)\u003c/pre\u003e\n\n\u003cp\u003e\n  Xmls also includes a helper function, make-node for creating xml nodes\n  of this form:\n\u003c/p\u003e\n\n\u003cpre\u003e\n(make-node \u0026amp;key name ns attrs children)\n\u003c/pre\u003e\n\n\u003cp\u003e\n  Xmls provides the corresponding accessor functions node-name, node-ns\n  node-attrs, and node-children.\n\u003c/p\u003e\n\n\u003ch3\u003eXML representation as s-expressions\u003c/h3\u003e\n\n\u003cp\u003eIn the s-expression representation, a node is represented as follows:\u003c/p\u003e\n\n\u003cpre\u003e\n(name (attributes) children*)\n\u003c/pre\u003e\n\n\u003cp\u003e\n  A name is either a simple string, if the element does not belong to a namespace,\n  or a list of (name namespace-url) if the element does belong to a namespace.\n\u003c/p\u003e\n\n\u003cp\u003e\n  Attributes are stored as (name value) lists.\n\u003c/p\u003e\n\n\u003cp\u003e\n  Children are stored as a list of either element nodes or text nodes.\n\u003c/p\u003e\n\n\u003cp\u003e\n  For example, the following xml document:\n\u003c/p\u003e\n\n\u003cpre\u003e\n\u0026lt;?xml version=\"1.0\"?\u0026gt;\n\u0026lt;!-- test document --\u0026gt;\n\u0026lt;book title='The Cyberiad'\u0026gt;\n  \u0026lt;!-- comment in here --\u0026gt;\n  \u0026lt;author xmlns='http://authors'\u0026gt;Stanislaw Lem\u0026lt;/author\u0026gt;\n  \u0026lt;info:subject xmlns:info='http://bookinfo' rank='1'\u0026gt;\u0026amp;quot;Cybernetic Fables\u0026amp;quot;\u0026lt;/info:subject\u0026gt;\n\u0026lt;/book\u0026gt;\n\u003c/pre\u003e\n\nWould parse as:\n\n\u003cpre\u003e\n(\"book\" ((\"title\" \"The Cyberiad\"))\n ((\"author\" . \"http://authors\") NIL \"Stanislaw Lem\")\n ((\"subject\" . \"http://bookinfo\") ((\"rank\" \"1\")) \"\\\"Cybernetic Fables\\\"\"))\n\u003c/pre\u003e\n\n\u003ca  name=\"Compatibility\"\u003e\u003ch3\u003eBackward Compatibility\u003c/h3\u003e\u003c/a\u003e\n\n\u003cp\u003eTo detect whether in this version of XMLS the return value of \u003ccode\u003ePARSE\u003c/code\u003e will be a\nlist or a structure, check for the feature \u003ccode\u003e:XMLS-NODES-ARE-STRUCTS\u003c/code\u003e.\n\n\u003cp\u003eFor old code that wants XML parsed into lists, instead of\nstructures, you may replace calls to \u003ccode\u003e(parse str)\u003c/code\u003e with\n\u003ccode\u003e(node-\u0026gt;nodelist (parse str))\u003c/code\u003e.\u003c/p\u003e\n\n\u003cp\u003eFor greater convenience, we offer \u003ccode\u003ePARSE-TO-LIST\u003c/code\u003e, which\nperforms the same function.\u003c/p\u003e\n\n\u003ch2\u003eUsage\u003c/h2\u003e\n\n\u003cp\u003e\n  The interface is straightforward.  The two main functions are\n  \u003ccode\u003ePARSE\u003c/code\u003e and \u003ccode\u003eTOXML\u003c/code\u003e.\n\u003c/p\u003e\n\n\u003cpre\u003e\n(parse source \u0026amp;key (compress-whitespace t) (quash-errors t)\n\u003c/pre\u003e\n\n\u003cp\u003e\n  Parse accepts either a string or an input stream and attempts to parse the xml\n  document contained therein.  It will return the s-expr parse tree if it's\n  successful or nil if parsing fails.\u003c/p\u003e\n\n\u003cp\u003e\n  If \u003ccode\u003eCOMPRESS-WHITESPACE\u003c/code\u003e is non-\u003ccode\u003eNIL\u003c/code\u003e, content nodes will be trimmed of whitespace and\n  empty whitespace strings between nodes will be discarded.\n\u003c/p\u003e\n\n\n\u003cpre\u003e\n(parse-to-list source (\u0026rest args))\n\u003c/pre\u003e\n\n\u003cp\u003eFunctions as \u003ccode\u003ePARSE\u003c/code\u003e, but returns a list representation\nof the XML document, instead of a structure.\u003c/p\u003e\n\n\u003cpre\u003e\n(write-prologue xml-decl doctype stream)\n\u003c/pre\u003e\n\n\u003cp\u003e\n  write-prologue writes the leading\n  \u003ccode\u003e\u0026lt;?xml ... ?\u0026gt;\u003c/code\u003e and \u003ccode\u003e\u0026lt;!DOCTYPE ... \u0026gt;\u003c/code\u003e\n  elements to \u003ccode\u003estream\u003c/code\u003e.\n  \u003ccode\u003exml-decl\u003c/code\u003e is an alist of attribute name value pairs.\n  Valid xml-decl attributes per the xml spec are \"version\", \"encoding\",\n  and \"standalone\", though write-prologue does not verify this.\n  \u003ccode\u003edoctype\u003c/code\u003e is a string containing the document type definition.\n\u003c/p\u003e\n\n\u003cpre\u003e\n(write-prolog xml-decl doctype stream)\n\u003c/pre\u003e\n\u003cp\u003e\nU.S. spelling alternative to \u003ccode\u003ewrite-prologue\u003c/code\u003e.\n\u003c/p\u003e\n\n\u003cpre\u003e\n(write-xml xml stream \u0026amp;key (indent nil))\n\u003c/pre\u003e\n\n\u003cp\u003e\n  write-xml accepts a lisp list in the format described above and writes the\n  equivalent xml string to stream.  Currently, if nodes use namespaces xmls will not \n  assign namespaces prefixes but will explicitly assign the namespace to each node.  This\n  will be changed in a later release.\n\n  Xmls will indent the generated xml output if indent is non-nil.\n\u003c/p\u003e\n\n\u003cpre\u003e\n(toxml node \u0026amp;key (indent nil))\n\u003c/pre\u003e\n\n\u003cp\u003e\n  \u003ccode\u003eTOXML\u003c/code\u003e is a convenience wrapper around write-xml that returns the in a newly\n  allocated string.\n\u003c/p\u003e\n\n\u003ca name=\"translators\"\u003e\u003ch3\u003eTranslating to and from s-expressions\u003c/h3\u003e\u003c/a\u003e\n\n\u003cp\u003eXMLS provides two exported functions to translate between the CL\nstructure representation of the XML tree and the s-expression\nrepresentation:\u003c/p\u003e\n\u003cdl\u003e\n  \u003cdt\u003e\u003ccode\u003enode-\u0026gt;nodelist\u003c/code\u003e\u003c/dt\u003e\n  \u003cdd\u003eTranslate the structure representation into s-expressions.\u003c/dd\u003e\n\n  \u003cdt\u003e\u003ccode\u003enodelist-\u0026gt;nodes\u003c/code\u003e\u003c/dt\u003e\n  \u003cdd\u003eTranslate the s-expression representation of an XMLS parse tree\n  into lisp structures.\u003c/dd\u003e\n\u003c/dl\u003e\n\n\n\u003ch3\u003eHelper functions\u003c/h3\u003e\n\n\u003cp\u003eThese are intended to allow programmers to avoid direct manipulation of the\n XMLS element representation.  If you use these, your code should be easier to\n  read and you will avoid problems if there is a change in internal\n  representation (such changes would be hard to even find, much less correct, if\n  using the lists directly).\u003c/p\u003e\n\n\u003cdl\u003e\n  \u003cdt\u003e\u003ccode\u003e\n      make-xmlrep  (tag \u0026amp;key attribs children)\n  \u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003eConstructor function.\u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-add-child! (xmlrep child)\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003eAdd a new child node to the XMLREP node.\u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-tag (xmlrep)\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003eExtract the tag from XMLREP.\u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-tagmatch (tag treenode)\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003eReturns true if TAG is the tag of TREENODE.  Match is\n    case \u003cem\u003einsensitive\u003c/em\u003e (quite possibly this is the Wrong Thing). \u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-attribs (xmlrep)\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003eExtract the attributes from an XMLREP node.\u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-children (xmlrep)\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003eExtract the children from an XMLREP node.\u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-find-child-tags (tag treenode)\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003e\n    Return all of the (direct) children of TREENODE whose tags are TAG.\n    Matching done by \u003ca href=\"#xmlrep-tagmatch\"\u003e\u003ccode\u003exmlrep-tagmatch\u003c/code\u003e\u003c/a\u003e.\n  \u003c/dd\u003e\n  \n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-find-child-tag (tag treenode \u0026amp;optional (if-unfound :error))\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003e\n    Find a \u003cem\u003esingle\u003c/em\u003e child of TREENODE with TAG.  Returns an error\n    if there is more or less than one such child.\n  \u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-string-child (treenode \u0026amp;optional (if-unfound :error))\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003e\n    Returns the \u003cem\u003esingle\u003c/em\u003e string-valued child of TREENODE.\n    If there is more than one child, or if a single child is not\n    a simple value, returns IF-UNFOUND, which defaults to :ERROR.\n  \u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-integer-child (treenode)\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003e\n    Find the \u003cem\u003esingle\u003c/em\u003e child of TREENODE whose value is a string that\n    can be parsed into an integer.  Returns an\n    error if there is more than one child, or if a single child is not\n    appropriately valued.\n  \u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-attrib-value (attrib treenode \u0026amp;optional (if-undefined :error))\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003e\n    Find the value of ATTRIB, a string, in TREENODE.\n    if there is no ATTRIB, will return the value of IF-UNDEFINED,\n    which defaults to :ERROR.\n  \u003c/dd\u003e\n\n  \u003cdt\u003e\n    \u003ccode\u003exmlrep-boolean-attrib-value (attrib treenode \u0026amp;optional (if-undefined :error))\u003c/code\u003e\n  \u003c/dt\u003e\n  \u003cdd\u003e\n    Find the value of ATTRIB, a string, in TREENODE.\n    The value should be either \"true\" or \"false\".  The\n    function will return T or NIL, accordingly.  If there is no ATTRIB,\n    will return the value of IF-UNDEFINED, which defaults to :ERROR.\n  \u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003ca  name=\"octets\"\u003e\u003ch2\u003eXMLS/Octets\u003c/h2\u003e\u003c/a\u003e\n\u003cp\u003e\nXMLS itself simply processes strings or streams.  This means that it\ndoes not provide native support for handling character encodings, as\ndeclared in the XML headers.  The system \u003ccode\u003exmls/octets\u003c/code\u003e,\nwhich depends on \u003ccode\u003exmls\u003c/code\u003e provides that support with the\nexported function \u003ccode\u003emake-xml-stream\u003c/code\u003e, which takes an\noctet-stream as argument, processes its header, choosing the\nappropriate character encoding, and then returns a stream suitable for\npassing to \u003ccode\u003exmls:parse\u003c/code\u003e.\u003c/p\u003e\n\n\u003cp\u003eProbably \u003ccode\u003emake-xml-stream\u003c/code\u003e should be made generic, and support\narguments of other types (e.g., strings interpreted as filenames,\npathnames, etc.).\u003c/p\u003e\n\n\u003ch2\u003eInstallation\u003c/h2\u003e\n\n\u003cp\u003e\n  xmls can be installed as an asdf system.  An asdf\n  system definition is provided with the distribution.\n\u003c/p\u003e \n\u003cp\u003ePrevious versions of XMLS were single files, and could be installed simply by\n  loading the file xmls.lisp.  This option is no longer supported.\u003c/p\u003e\n \n\u003ch2\u003eContact Information\u003c/h2\u003e \n \n\u003cp\u003e \n  Please contact Robert Goldman, rpgoldman AT sift.net with any \n  questions or bug reports.\n\u003c/p\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n","funding_links":[],"categories":["Expert Systems"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frpgoldman%2Fxmls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frpgoldman%2Fxmls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frpgoldman%2Fxmls/lists"}