Skip to content

Repository files navigation

xmlalt

Proof of Concept - Converter of XML to alternative formats (see the description of the idea).

In short, it's easy to design formats alternative to XML that are oriented to search/query, simple parsing (even with Bash), etc. This Common Lisp is just a simple proof of concept, demonstrating conversion of XML to 2 such alternative formats: REGFMT and CMDFMT:

  • REGFMT is oriented to simple querying with grep, awk, etc. Conceptually it reminds lines of Windows .reg files
  • CMDFMT is oriented to simple parsing with awk, Bash and similar. Conceptually consists of short lines perfect for parsing with FSM.

Examples:

Considering such XML:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ELEMENT root (#PCDATA | lib)*>
  <!ATTLIST root id ID #REQUIRED>

  <!ELEMENT lib (#PCDATA | book | xxx)*>
  <!ELEMENT book (#PCDATA)>
  <!ELEMENT xxx EMPTY>

  <!NOTATION png SYSTEM "image/png">
  <!ENTITY internal "InternalEntityValue">
  <!ENTITY ext SYSTEM "external.xml">
  <!ENTITY logo SYSTEM "logo.png" NDATA png>
]>

<root xmlns="urn:default" xmlns:x="urn:x" id="r1">
  <!-- A comment -->
  <![CDATA[Some CDATA text]]>
  <?pi processing instruction?>
  Text &amp; more &#x1F600; &internal;
  <lib xmlns="urn:yyy">
    <book>Book1</book>
    <book>Book2</book>
    <xxx/>
  </lib>
  Other text!!!
  <lib>
    <book>Book3</book>
  </lib>
</root>

we can get such REGFMT analogue:

::<children> = 3
::<comment> =  <<>!DOCTYPE root SYSTEM "t1.dtd"<>> 
<dtd>::<name> = root
<dtd>::<element>::<name> = root
<dtd>::<element>::<model> = (* (OR PCDATA lib))
<dtd>::<attribute>::<element-name> = root
<dtd>::<attribute>::<attribute-name> = id
<dtd>::<attribute>::<type> = ID
<dtd>::<attribute>::<default> = REQUIRED
<dtd>::<element>::<name> = lib
<dtd>::<element>::<model> = (* (OR PCDATA book xxx))
<dtd>::<element>::<name> = book
<dtd>::<element>::<model> = PCDATA
<dtd>::<element>::<name> = xxx
<dtd>::<element>::<model> = EMPTY
<dtd>::<notation>::<name> = png
<dtd>::<notation>::<system-id> = image/png
<dtd>::<internal-entity>::<kind> = GENERAL
<dtd>::<internal-entity>::<name> = internal
<dtd>::<internal-entity>::<value> = InternalEntityValue
<dtd>::<external-entity>::<kind> = GENERAL
<dtd>::<external-entity>::<name> = ext
<dtd>::<external-entity>::<system-id> = external.xml
<dtd>::<unparsed-entity>::<name> = logo
<dtd>::<unparsed-entity>::<system-id> = logo.png
<dtd>::<unparsed-entity>::<notation-name> = png
root::<children> = 7
root::<namespace-uri> = urn:default
root::<qname> = root
root::<prefix-mapping> = urn:yyy
root::<prefix-mapping>::x = urn:x
root::<prefix-mapping> = urn:default
root::@xmlns = urn:default
root::@xmlns::<namespace-uri> = http://www.w3.org/2000/xmlns/
root::@xmlns:x = urn:x
root::@xmlns:x::<local-name> = x
root::@xmlns:x::<namespace-uri> = http://www.w3.org/2000/xmlns/
root::@id = r1
root::@id::<local-name> = id
root::<comment> =  A comment 
root::<cdata> = Some CDATA text
root::<processing-instruction>::pi = processing instruction
root::<text> = Text & more 😀InternalEntityValue
root::<0>::lib::<children> = 3
root::<0>::lib::<namespace-uri> = urn:yyy
root::<0>::lib::<qname> = lib
root::<0>::lib::<prefix-mapping> = urn:yyy
root::<0>::lib::<prefix-mapping>::x = urn:x
root::<0>::lib::<prefix-mapping> = urn:default
root::<0>::lib::@xmlns = urn:yyy
root::<0>::lib::@xmlns::<namespace-uri> = http://www.w3.org/2000/xmlns/
root::<0>::lib::<0>::book::<children> = 1
root::<0>::lib::<0>::book::<namespace-uri> = urn:yyy
root::<0>::lib::<0>::book::<qname> = book
root::<0>::lib::<0>::book::<prefix-mapping> = urn:yyy
root::<0>::lib::<0>::book::<prefix-mapping>::x = urn:x
root::<0>::lib::<0>::book::<prefix-mapping> = urn:default
root::<0>::lib::<0>::book::<text> = Book1
root::<0>::lib::<1>::book::<children> = 1
root::<0>::lib::<1>::book::<namespace-uri> = urn:yyy
root::<0>::lib::<1>::book::<qname> = book
root::<0>::lib::<1>::book::<prefix-mapping> = urn:yyy
root::<0>::lib::<1>::book::<prefix-mapping>::x = urn:x
root::<0>::lib::<1>::book::<prefix-mapping> = urn:default
root::<0>::lib::<1>::book::<text> = Book2
root::<0>::lib::xxx::<namespace-uri> = urn:yyy
root::<0>::lib::xxx::<qname> = xxx
root::<0>::lib::xxx::<prefix-mapping> = urn:yyy
root::<0>::lib::xxx::<prefix-mapping>::x = urn:x
root::<0>::lib::xxx::<prefix-mapping> = urn:default
root::<text> = Other text!!!
root::<1>::lib::<children> = 1
root::<1>::lib::<namespace-uri> = urn:default
root::<1>::lib::<qname> = lib
root::<1>::lib::book::<children> = 1
root::<1>::lib::book::<namespace-uri> = urn:default
root::<1>::lib::book::<qname> = book
root::<1>::lib::book::<text> = Book3

similar to CMDFMT:

.COM
 <!DOCTYPE root SYSTEM "t1.dtd"> 
.COME
.DTD
.DTD.NAME root
.DTD.EL.NAME root
.DTD.EL.MODEL (* (OR PCDATA lib))
.DTD.ATTR.EL.NAME root
.DTD.ATTR.ATTR.NAME id
.DTD.ATTR.TYPE ID
.DTD.ATTR.DEF REQUIRED
.DTD.EL.NAME lib
.DTD.EL.MODEL (* (OR PCDATA book xxx))
.DTD.EL.NAME book
.DTD.EL.MODEL PCDATA
.DTD.EL.NAME xxx
.DTD.EL.MODEL EMPTY
.DTD.NOTA.NAME png
.DTD.NOTA.SYS.ID image/png
.DTD.INT.ENT.KIND GENERAL
.DTD.INT.ENT.NAME internal
.DTD.INT.ENT.VALUE InternalEntityValue
.DTD.EXT.ENT.KIND GENERAL
.DTD.EXT.ENT.NAME ext
.DTD.EXT.SYS.ID external.xml
.DTD.UNP.ENT.NAME logo
.DTD.UNP.ENT.SYS.ID logo.png
.DTD.UNP.ENT.NOTA.NAME png
.DTDE
.EL 7 root
.EL.NS urn:default
.EL.LOC.NAME root
.EL.QNAME root
.EL.PREF.MAP NIL urn:yyy
.EL.PREF.MAP x urn:x
.EL.PREF.MAP NIL urn:default
.EL.ATTR xmlns urn:default http://www.w3.org/2000/xmlns/ T
.EL.ATTR x xmlns:x urn:x http://www.w3.org/2000/xmlns/ T
.EL.ATTR id id r1 T
.COM
 A comment 
.COME
.CD
Some CDATA text
.CDE
.PI.TARG pi
.PI
processing instruction
.PIE
.TEXT
Text & more 😀InternalEntityValue
.TEXTE
.EL 3 root/lib
.EL.NS urn:yyy
.EL.LOC.NAME lib
.EL.QNAME lib
.EL.PREF.MAP NIL urn:yyy
.EL.PREF.MAP x urn:x
.EL.PREF.MAP NIL urn:default
.EL.ATTR xmlns urn:yyy http://www.w3.org/2000/xmlns/ T
.EL 1 root/lib/book
.EL.NS urn:yyy
.EL.LOC.NAME book
.EL.QNAME book
.EL.PREF.MAP NIL urn:yyy
.EL.PREF.MAP x urn:x
.EL.PREF.MAP NIL urn:default
.TEXT
Book1
.TEXTE
.ELE root/lib/book
.EL 1 root/lib/book
.EL.NS urn:yyy
.EL.LOC.NAME book
.EL.QNAME book
.EL.PREF.MAP NIL urn:yyy
.EL.PREF.MAP x urn:x
.EL.PREF.MAP NIL urn:default
.TEXT
Book2
.TEXTE
.ELE root/lib/book
.EL 0 root/lib/xxx
.EL.NS urn:yyy
.EL.LOC.NAME xxx
.EL.QNAME xxx
.EL.PREF.MAP NIL urn:yyy
.EL.PREF.MAP x urn:x
.EL.PREF.MAP NIL urn:default
.ELE root/lib/xxx
.ELE root/lib
.TEXT
Other text!!!
.TEXTE
.EL 1 root/lib
.EL.NS urn:default
.EL.LOC.NAME lib
.EL.QNAME lib
.EL 1 root/lib/book
.EL.NS urn:default
.EL.LOC.NAME book
.EL.QNAME book
.TEXT
Book3
.TEXTE
.ELE root/lib/book
.ELE root/lib
.ELE root

Example of query

Select all text nodes from root/**/lib/:

$ ./xmlalt -i t1.xml --from XMLFMT --to REGFMT|grep 'root::.*::lib.*::<text>'
root::<0>::lib::<0>::book::<text> = Book1
root::<0>::lib::<1>::book::<text> = Book2
root::<1>::lib::book::<text> = Book3

How to build the project

You need Linux, MacOS or WSL, Cygwin...

  • Install SBCL, qlot
  • Run qlot install to obtain all dependencies (see qlfile)
  • Run qlot exec ./build.sh

Ideas

Deserialization for CMDFMT, REGFMT to be able to convert CMDFMT to XML or to REGFMT, etc. They should be able to deserialize partial files where it makes sense.

About

Converter of XML to alternative formats

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages