Mercurial Hosting > luan
changeset 1790:a8c685a894b4
start xml work
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 25 Dec 2023 23:07:59 -0700 |
parents | bac27b119ff2 |
children | f8f5c51f5b36 |
files | src/goodjava/xml/Xml.java src/goodjava/xml/XmlElement.java src/goodjava/xml/XmlParser.java src/luan/modules/Xml.luan src/luan/modules/parsers/Xml.java |
diffstat | 5 files changed, 139 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/goodjava/xml/Xml.java Mon Dec 25 23:07:59 2023 -0700 @@ -0,0 +1,27 @@ +package goodjava.xml; + + +public final class Xml { + public String declaration; + private XmlElement element; + + public XmlElement getElement() { + return element; + } + + public void setElement(XmlElement element) { + if( element == null ) + throw new IllegalArgumentException("element can't be null"); + this.element = element; + } + + @Override public String toString() { + StringBuilder sb = new StringBuilder(); + if( declaration != null ) { + sb.append( declaration ); + sb.append( '\n' ); + } + element.toString(sb,0); + return sb.toString(); + } +}
--- a/src/goodjava/xml/XmlElement.java Sun Dec 24 16:52:35 2023 -0700 +++ b/src/goodjava/xml/XmlElement.java Mon Dec 25 23:07:59 2023 -0700 @@ -6,7 +6,7 @@ public final class XmlElement { public final String name; public final Map<String,String> attributes; - public final Object content; + private Object content = null; public XmlElement(String name,Map<String,String> attributes) { this.name = name; @@ -14,31 +14,35 @@ this.content = null; } - public XmlElement(String name,Map<String,String> attributes,String content) { + public Object getContent() { + return content; + } + + public void removeContent() { + content = null; + } + + public void setContent(String content) { if( content == null ) throw new IllegalArgumentException("content can't be null"); - this.name = name; - this.attributes = attributes; this.content = content; } - public XmlElement(String name,Map<String,String> attributes,XmlElement[] content) { + public void setContent(XmlElement[] content) { if( content == null ) throw new IllegalArgumentException("content can't be null"); if( content.length == 0 ) throw new IllegalArgumentException("content can't be empty"); - this.name = name; - this.attributes = attributes; this.content = content; } - public String toString() { + @Override public String toString() { StringBuilder sb = new StringBuilder(); toString(sb,0); return sb.toString(); } - private void toString(StringBuilder sb,int indented) { + void toString(StringBuilder sb,int indented) { indent(sb,indented); sb.append( '<' ); sb.append( name ); @@ -100,6 +104,12 @@ case '\'': buf.append("'"); break; + case '\n': + buf.append(" "); + break; + case '\r': + buf.append(" "); + break; default: buf.append(c); }
--- a/src/goodjava/xml/XmlParser.java Sun Dec 24 16:52:35 2023 -0700 +++ b/src/goodjava/xml/XmlParser.java Mon Dec 25 23:07:59 2023 -0700 @@ -5,13 +5,15 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.ArrayList; +import java.util.regex.Pattern; +import java.util.regex.Matcher; import goodjava.parser.Parser; import goodjava.parser.ParseException; public final class XmlParser { - public static XmlElement parse(String text) throws ParseException { + public static Xml parse(String text) throws ParseException { return new XmlParser(text).parse(); } @@ -25,9 +27,10 @@ return new ParseException(parser,msg); } - private XmlElement parse() throws ParseException { + private Xml parse() throws ParseException { + Xml xml = new Xml(); spaces(); - prolog(); + xml.declaration = declaration(); spaces(); XmlElement element = element(); spaces(); @@ -35,15 +38,19 @@ throw exception("unexpected text"); if( element==null ) throw exception("empty document not allowed"); - return element; + xml.setElement(element); + return xml; } - private void prolog() throws ParseException { + private String declaration() throws ParseException { + int start = parser.begin(); if( !parser.match("<?xml") ) - return; + return parser.failure(null); while( attribute() != null ); spaces(); required("?>"); + String s = parser.textFrom(start); + return parser.success(s); } private XmlElement element() throws ParseException { @@ -67,12 +74,14 @@ required(">"); String s = string(name); if( s != null ) { - XmlElement element = new XmlElement(name,attributes,s); + XmlElement element = new XmlElement(name,attributes); + element.setContent(s); return parser.success(element); } List<XmlElement> elements = elements(name); if( elements != null ) { - XmlElement element = new XmlElement(name,attributes,elements.toArray(new XmlElement[0])); + XmlElement element = new XmlElement(name,attributes); + element.setContent( elements.toArray(new XmlElement[0]) ); return parser.success(element); } throw exception("bad element"); @@ -177,7 +186,19 @@ return parser.anyOf(" \t\r\n"); } + private static final Pattern dec = Pattern.compile("&#(\\d+);"); + private static String decode(String s) { + Matcher m = dec.matcher(s); + StringBuffer sb = new StringBuffer(); + while( m.find() ) { + String d = m.group(1); + int i = Integer.parseInt(d); + d = String.valueOf((char)i); + m.appendReplacement(sb, d); + } + m.appendTail(sb); + s = sb.toString(); s = s.replace("<","<"); s = s.replace(">",">"); s = s.replace(""","\"");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/Xml.luan Mon Dec 25 23:07:59 2023 -0700 @@ -0,0 +1,49 @@ +require "java" +local XmlParser = require "java:goodjava.xml.XmlParser" +local XmlElement = require "java:goodjava.xml.XmlElement" +local Luan = require "luan:Luan.luan" +local error = Luan.error +local set_metatable = Luan.set_metatable or error() + + +local Xml = {} + +Xml.encode = XmlElement.encode + +local function new(java,mt) + local t = {} + t.java = java + set_metatable(t,mt) + return t +end + +local element_mt = {} + +local xml_mt = {} +function xml_mt.__index(xml,key) + if key == "element" then + return new( xml.java.element, element_mt ) + end + if key == "declaration" then + return xml.java.declaration + end + return nil +end +function xml_mt.__new_index(xml,key,value) + if key == "element" then + xml.java.setElement( value.java ) + elseif key == "declaration" then + xml.java.declaration = value + else + error("invalid key: "..key) + end +end +function xml_mt.__to_string(xml) + return xml.java.toString() +end + +function Xml.parse(text) + return new( XmlParser.parse(text), xml_mt ) +end + +return Xml
--- a/src/luan/modules/parsers/Xml.java Sun Dec 24 16:52:35 2023 -0700 +++ b/src/luan/modules/parsers/Xml.java Mon Dec 25 23:07:59 2023 -0700 @@ -52,19 +52,25 @@ private static XmlElement element(String name,Object obj) throws LuanException { if( obj instanceof String ) { - return new XmlElement( name, Collections.emptyMap(), (String)obj ); + XmlElement element = new XmlElement( name, Collections.emptyMap() ); + element.setContent( (String)obj ); + return element; } LuanTable t = (LuanTable)obj; Map<String,String> attributes = attributes(t); String s = (String)t.rawGet(TEXT); if( s != null ) { - return new XmlElement(name,attributes,s); + XmlElement element = new XmlElement(name,attributes); + element.setContent(s); + return element; } else { XmlElement[] elements = elements(t); if( elements.length==0 ) { return new XmlElement(name,attributes); } else { - return new XmlElement(name,attributes,elements); + XmlElement element = new XmlElement(name,attributes); + element.setContent(elements); + return element; } } } @@ -85,7 +91,7 @@ public static LuanTable parse(String s) throws ParseException, LuanException { - XmlElement element = XmlParser.parse(s); + XmlElement element = XmlParser.parse(s).getElement(); LuanTable tbl = new LuanTable(); addElements(tbl,new XmlElement[]{element}); return tbl; @@ -101,12 +107,13 @@ } t.rawPut( ATTRIBUTES, attrs ); } - if( element.content == null ) { + Object content = element.getContent(); + if( content == null ) { // nothing - } else if( element.content instanceof String ) { - t.rawPut( TEXT, element.content ); + } else if( content instanceof String ) { + t.rawPut( TEXT, content ); } else { - XmlElement[] els = (XmlElement[])element.content; + XmlElement[] els = (XmlElement[])content; addElements(t,els); } LuanTable old = (LuanTable)tbl.rawGet(element.name);