view src/luan/modules/parsers/Xml.java @ 1468:35f3bfd4f51d

xml
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 14 Apr 2020 08:44:33 -0600
parents 670b7d089699
children f5b8c7e1ac82
line wrap: on
line source

package luan.modules.parsers;

import java.util.Collections;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ArrayList;
import goodjava.parser.ParseException;
import goodjava.xml.XmlElement;
import goodjava.xml.XmlParser;
import luan.Luan;
import luan.LuanTable;
import luan.LuanException;


public final class Xml {

	public static String toString(LuanTable tbl) throws LuanException {
		XmlElement[] elements = elements(tbl);
		if( elements.length != 1 )
			throw new LuanException("XML must have 1 root element");
		return elements[0].toString();
	}

	private static final Integer ONE = Integer.valueOf(1);
	private static final Integer TWO = Integer.valueOf(2);

	private static XmlElement[] elements(LuanTable tbl) throws LuanException {
		List<XmlElement> list = new ArrayList<XmlElement>();
		for( Map.Entry entry : tbl.iterable() ) {
			Object key = entry.getKey();
			if( key.equals(ONE) )
				continue;
			if( !(key instanceof String) )
				throw new LuanException("XML key must be string");
			String name = (String)key;
			Object value = entry.getValue();
			XmlElement element;
			if( value instanceof String ) {
				String s = (String)value;
				element = new XmlElement(name,Collections.emptyMap(),s);
			} else {
				LuanTable t = (LuanTable)value;
				Map<String,String> attributes = attributes(t);
				String s = (String)t.get(TWO);
				if( s != null ) {
					element = new XmlElement(name,attributes,s);
				} else {
					XmlElement[] elements = elements(t);
					if( elements.length==0 ) {
						element = new XmlElement(name,attributes);
					} else {
						element = new XmlElement(name,attributes,elements);
					}
				}
			}
			list.add(element);
		}
		return list.toArray(new XmlElement[0]);
	}

	private static Map<String,String> attributes(LuanTable tbl) throws LuanException {
		Object obj = tbl.get(ONE);
		if( obj==null )
			return Collections.emptyMap();
		LuanTable t = (LuanTable)obj;
		Map<String,String> map = new LinkedHashMap<String,String>();
		for( Map.Entry entry : t.iterable() ) {
			String name =(String)entry.getKey();
			String value =(String)entry.getValue();
			map.put(name,value);
		}
		return map;
	}


	public static LuanTable parse(Luan luan,String s) throws ParseException, LuanException {
		XmlElement element = XmlParser.parse(s);
		LuanTable tbl = new LuanTable(luan);
		addElements(tbl,new XmlElement[]{element});
		return tbl;
	}

	private static LuanTable addElements(LuanTable tbl,XmlElement[] elements) throws LuanException {
		for( XmlElement element : elements ) {
			LuanTable t = new LuanTable(tbl.luan());
			if( !element.attributes.isEmpty() ) {
				LuanTable attrs = new LuanTable(tbl.luan());
				for( Map.Entry<String,String> entry : element.attributes.entrySet() ) {
					attrs.put(entry.getKey(),entry.getValue());
				}
				t.put( 1, attrs );
			}
			if( element.content == null ) {
				tbl.put(element.name,t);
			} else if( element.content instanceof String ) {
				if( t.isEmpty() ) {
					tbl.put(element.name,element.content);
				} else {
					t.put( 2, element.content );
					tbl.put(element.name,t);
				}
			} else {
				XmlElement[] els = (XmlElement[])element.content;
				addElements(t,els);
				tbl.put(element.name,t);
			}
		}
		return tbl;
	}

}