if not(IsBound(xml)) then
  NewType("xml",0);
fi;

_PrintXML:=
  function(xml)
    Print("XML Data Structure");
  end;

## initialise an XML tree structure
InitialiseXML:=
  function(arg)
    local rootelm;
    CheckArgs(arg,["rootelm"],["xml"]);
    rootelm:=__ARGREC.("rootelm");
    
    return
      rec(
        root:=rootelm,
        type:=xml,
        operations:=
          rec(
            Print:=_PrintXML)
        );
  end;

AttachRootElement:=
  function(xml,elm)
    ##
    return xml;
  end;

AttachElement:=
  function(xml,elm)
    ##
    return xml;
  end;

PrintDocumentationAsXML:=
  function(hash)
    local xmlout;
    xmlout:=InitialiseXML;
    return xmlout;
  end;


_QuoteStringForXML:=
  function(strin)
    strin:=
      Replace(strin,"&","&amp;");
    strin:=
      Replace(strin,"\"","&quot;");
    strin:=
      Replace(strin,"<","&lt;");
    strin:=
      Replace(strin,">","&gt;");
    strin:=
      Replace(strin,"\n","<br/>\n");
    return strin;
  end;

##
## major XMLise-with-depth functions
PrintWalkedXML:=
  function(trec)
    local trecf;
    if Type(trec)=record then
      trecf:=RecFields(trec);
      if "kind" in trecf then
        Print("<",trec.("kind"),">");
        if "node" in trecf then
          PrintWalkedXML(trec.("node"));
        fi;
        Print("</",trec.("kind"),">");
      fi;
    elif Type(trec)=type then
      Print(trec);
    elif Type(trec)=list then
      Mapc(PrintWalkedXML,trec);
    else
      Print("unsupported: ",trec,"\n");
    fi;
  end;

PrintXMLisedType:=
  function(type)
    local ttree;
    ttree:=TypeToTree(type);
    PrintWalkedXML(ttree);
  end;

## more trivial output routines

PrintXMLname:=
  function(docrec,indent)
    Print(indent*" ","<name>",
      _QuoteStringForXML(GetEntry(docrec,"name",rec(Fail:="unknown"))),
      "</name>\n");
  end;
_PrintXMLargs:=
  function(sin,indent)
    Print(indent*" ","<arg");
    if IsBound(sin[2]) then
      Print(" name=\"",sin[2],"\"");
    fi;
    if IsBound(sin[1]) then
      Print(" filename=\"",DocHash(SPrint(sin[1])),"\"");
    fi;
    if IsBound(sin[4]) then
      Print(" default=\"",_QuoteStringForXML(SPrint(GetEntry(sin[4],"Default",rec(Fail:="")))),"\"");
    fi;
    if IsBound(sin[3]) then
      Print(" description=\"",_QuoteStringForXML(sin[3]),"\"");
    fi;
    Print(">\n");
    if IsBound(sin[1]) then
      Print((indent+2)*" ");
      PrintXMLisedType(sin[1]);
      Print("\n");
    fi;
    Print(indent*" ","</arg>\n");
  end;
PrintXMLinargs:=
  function(docrec,indent)
    local sin;
    sin:=GetEntry(docrec,"sin");
    if IsSuccess(sin) then
      Print(indent*" ","<inargs>\n");
      Mapc(i->_PrintXMLargs(i,indent+2),sin);
      Print(indent*" ","</inargs>\n");
    fi;
  end;
PrintXMLoutargs:=
  function(docrec,indent)
    local sou;
    sou:=GetEntry(docrec,"sou");
    if IsSuccess(sou) then
      Print(indent*" ","<outargs>\n");
      Mapc(i->_PrintXMLargs(i,indent+2),sou);
      Print(indent*" ","</outargs>\n");
    fi;
  end;
PrintXMLoptargs:=
  function(docrec,indent)
    local opt;
    opt:=GetEntry(docrec,"opt");
    if IsSuccess(opt) then
      Print(indent*" ","<optargs>\n");
      Mapc(i->_PrintXMLargs(i,indent+2),opt);
      Print(indent*" ","</optargs>\n");
    fi;
  end;
PrintXMLsyntax:=
  function(docrec,indent)
    local syn;
    syn:=GetEntry(docrec,"syntax");
    if IsSuccess(syn) then
      Print(indent*" ","<syntax>\n");
      ## fsck have to quote stuff :\
      ## < -> &lt;
      ## > -> &gt;
      Print((2+indent)*" ",_QuoteStringForXML(syn),"\n");
      Print(indent*" ","</syntax>\n");
    fi;
  end;
PrintXMLsignature:=
  function(docrec,indent)
    Print(indent*" ","<signature>\n");
    PrintXMLname(docrec,indent+2);
    PrintXMLinargs(docrec,indent+2);
    PrintXMLoutargs(docrec,indent+2);
    PrintXMLoptargs(docrec,indent+2);
    PrintXMLsyntax(docrec,indent+2);
    Print(indent*" ","</signature>\n");
  end;

PrintXMLshort:=
  function(docrec,indent)
    Print(indent*" ","<shortdoc>\n");
    Print((2+indent)*" ",_QuoteStringForXML(GetEntry(docrec,"short",rec(Fail:=""))),"\n");
    Print(indent*" ","</shortdoc>\n");
  end;
_PrintXMLex:=
  function(ex,indent)
    Print(indent*" ","<example>\n");
    Print((2+indent)*" ","<input>\n");
    Print((4+indent)*" ",_QuoteStringForXML(ex),"\n");
    Print((2+indent)*" ","</input>\n");
    Print(indent*" ","</example>\n");
  end;
PrintXMLexamples:=
  function(docrec,indent)
    Print(indent*" ","<examples>\n");
    Mapc(i->_PrintXMLex(i,2+indent),GetEntry(docrec,"ex",rec(Fail:=[])));
    Print(indent*" ","</examples>\n");
  end;
_PrintXMLsee:=
  function(see,indent)
    if IsSuccess(Assoc(__DOC,see)) then
      Print(indent*" ","<see>",see,"</see>\n");
    fi;
  end;
PrintXMLseealso:=
  function(docrec,indent)
    Print(indent*" ","<seealso>\n");
    Mapc(i->_PrintXMLsee(i,2+indent),GetEntry(docrec,"see",rec(Fail:=[])));
    Print(indent*" ","</seealso>\n");
  end;
PrintXMLdocumentation:=
  function(docrec,indent)
    Print(indent*" ","<documentation>\n");
    PrintXMLshort(docrec,2+indent);
    PrintXMLexamples(docrec,2+indent);
    PrintXMLseealso(docrec,2+indent);
    Print(indent*" ","</documentation>\n");
  end;



PrintXML:=
  function(hash)
    local docrec,indent;
    indent:=2;
    docrec:=RetrieveDocumentation(hash);
    Print("<record name=\"",hash,"\" kind=\"",docrec.kind,"\">\n");
    PrintXMLsignature(docrec,indent);

    PrintXMLdocumentation(docrec,indent);

    Print("</record>\n");
  end;

PrintStruct:=
  function(struct,indent)
    Print(indent*" ", "<entry hash=\"",struct.main,"\">\n");
    if IsBound(struct.sub) then
      Mapc(i->PrintStruct(i, 2+indent), struct.sub);
    fi;
    Print(indent*" ", "</entry>\n");
  end;

DumpXML:=
  function(arg)
    SizeScreen([255,70]);
    Print("\n\n<database>\n\n");
    Mapc(PrintXML,__DOC.keys);
    Print("\n\n</database>\n");
  end;

## call like this DumpStruct(kashtut);
DumpStruct:=
  function(struct)
    SizeScreen([255,70]);
    Print("\n\n<struct>\n\n");
    PrintStruct(struct,2);
    Print("\n\n</struct>\n");
  end;


#<struct>
#  <main hash="938493">
#    <main 
