view dbus-d/dsrc/org/freedesktop/dbus/tool/XmlSupport.d @ 0:a5576806d36d

recreate repository without any libs for lightweight repository
author Frank Benoit <benoit@tionex.de>
date Sat, 20 Oct 2007 18:07:18 +0200
parents
children
line wrap: on
line source

/**
 * Author:    Frank Benoit
 * License:   Public domain
 * File type: D programming language
 */
module org.freedesktop.dbus.tool.XmlSupport;

import tango.core.Array;
import tango.io.FileConduit;

import tango.text.Util;
import tango.util.collection.LinkSeq;
import mango.xml.sax.DefaultSAXHandler;
import mango.xml.sax.parser.teqXML;

class Element {
    char[]         mName;
    Element[]      mChilds;
    char[][char[]] mAttributes;
    char[]         mText;
    Element mParent;

    public this( char[] aName, Element aParent ){
        mName   = aName.dup;
        mParent = aParent;
        mText   = "";
        if( aParent ){
            aParent.addChild( this );
        }
    }

    protected void addChild( Element aChild ){
        mChilds ~= aChild;
    }
    public Element createChildElement( char[] aName ){
        Element result = new Element( aName, this );
        return result;
    }
    public void completeChildElement( char[] aName, Element aChild ){
    }
    public void completeYourself(){
        mText = Text.trim( mText );
    }
    public char[] getText(){
        return mText;
    }
    public char[] getName(){
        return mName;
    }
    public void setText( char[] aText ){
        mText = aText.dup;
    }
    public void addAttribute(char[] key, char[] value){
        mAttributes[ key.dup ] = value.dup;
    }
    public bool hasAttribute( char[] aName ){
        return cast(bool)( aName in mAttributes );
    }
    public bool hasChild( char[] aName ){
        foreach( Element child; mChilds ){
            if( child.mName == aName ){
                return true;
            }
        }

        return false;
    }
    public Element tryGetChild( char[] aName ){
        foreach( Element child; mChilds ){
            if( child.mName == aName ){
                return child;
            }
        }

        return null;
    }
    public Element getChild( char[] aName ){
        Element result = tryGetChild( aName );
        check( result !is null, "Element.getChild mName=%0, aName=%1", mName, aName );
        return result;
    }
    public Element[] getChilds(){
        return mChilds.dup;
    }
    public Element[] getChilds( char[] aName ){
        Element[] result;
        foreach( Element child; mChilds ){
            if( child.mName == aName ){
                result ~= child;
            }
        }

        return result;
    }
    public Element tryFindChild( bool delegate( Element aChild ) aDg ){
        foreach( Element child; mChilds ){
            if( aDg( child ) ){
                return child;
            }
        }

        return null;
    }
    public Element findChild( bool delegate( Element aChild ) aDg ){
        Element result = tryFindChild( aDg );
        check( result !is null, "Element.findChild mName=%0, not found", mName );
        return result;
    }
    public char[] getAttribute( char[] aKey ){
        check( cast(bool)(aKey in mAttributes), "Element %0 does not contain the attribute %1", mName, aKey );
        return mAttributes[ aKey ].dup;
    }

    public void checkAllowedChilds( char[][] names... ){
        foreach( Element child; mChilds ){
            check( tango.core.Array.find( names, child.mName ) != names.length,
                "in element %0, a not allowed child node name exist %1", mName, child.mName );
        }
    }
}

class Document {
    private Element mElement;
    public Element createRootElement( char[] aName ){
        mElement = new Element( aName, null );
        return mElement;
    }
    public void completeRootElement( char[] aName, Element aChild ){
    }
    public void setRoot( Element aRoot ){
        mElement = aRoot;
    }
    public Element getRoot(){
        return mElement;
    }
}

public class DomConstructionSaxHandler : DefaultSAXHandler!( char ) {
    Document mDocument;
    alias LinkSeq!(Element) TElementList;
    TElementList mElements;

    public this( Document aDocument ){
        mElements = new TElementList();
        mDocument = aDocument;
    }
    void startDocument() {
        //Stdout( "startDocument" ).newline;
    }
    void endDocument() {
        //Stdout( "endDocument" ).newline;
    }
    void processingInstruction(char[] target, char[] data) {
        //Stdout( "processingInstruction" ).newline;
    }
    void startElement(char[] name) {
        if( mElements.size() > 0 ){
            //Stdout.format( "startElement {0} {1} ", name.utf8, mElements.size() ).newline;
            Element el = mElements.head().createChildElement( name );
            mElements.prepend( el );
        }
        else{
            //Stdout( "startRootElement" ~ name.utf8 ).newline;
            Element el = mDocument.createRootElement( name );
            mElements.prepend( el );
        }

        //Stdout( "startElement" ).newline;
    }
    void addAttribute(char[] key, char[] value) {
        Element el = mElements.head();
        el.addAttribute( key, value );
        //Stdout( "addAttribute" ).newline;
    }
    void endElement(char[] name) {
        Element child = mElements.take();
        child.completeYourself();
        if( mElements.size() > 0 ){
            Element el = mElements.head();
            el.completeChildElement( name, child );
        }
        else{
            mDocument.completeRootElement( name, child );
        }

        //Stdout( "endElement" ).newline;
    }
    void comment(char[] text) {
        //Stdout( "comment" ).newline;
    }
}

void check( bool aCondition, char[][] aMessage ... ){
    if( !aCondition ){
        char[200] buf;
        throw new Exception( layout( buf, aMessage ));
    }
}

Element parse(char[] aFileName){
    auto parser = new XMLReader!(char) ();
    auto doc = new Document();
    auto handler = new DomConstructionSaxHandler( doc );
    parser.parse( new FileConduit( aFileName ), handler);
    return doc.getRoot();
}