ref: 47a288683dbdc55c5df9b9f65db9909de6021af0
dir: /libxml/xmlprint.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <ctype.h> #include "xml.h" static void prval(Biobuf *bp, char *s) { char *p; Rune r; p = s; while(*p){ p += chartorune(&r, p); switch(r){ case L'&': Bprint(bp, "&"); break; case L'<': Bprint(bp, "<"); break; case L'>': Bprint(bp, ">"); break; case L'"': Bprint(bp, """); break; case L'\'': Bprint(bp, "'"); break; default: if(r >= L' ') Bprint(bp, "%C", r); else Bprint(bp, "&#x%04x;", r); break; } } } static void _xmlprint(Biobuf *bp, Elem *ep, int in) { Attr *ap; char *ns; enum {indent = 4}; for(; ep; ep = ep->next){ ns = ep->ns ? ep->ns->name : nil; Bprint(bp, "%*s<", in, ""); if (ns) Bprint(bp, "%s:", ns); Bprint(bp, "%s", ep->name); for (ap = ep->attrs; ap; ap = ap->next){ ns = ap->ns ? ap->ns->name : nil; Bprint(bp, " "); if (ns) Bprint(bp, "%s:", ns); Bprint(bp, "%s=\'", ap->name); prval(bp, ap->value); Bprint(bp, "\'"); } if(ep->child){ if(ep->pcdata){ Bprint(bp, ">\n%*s\n", in+indent, ""); prval(bp, ep->pcdata); } else Bprint(bp, ">\n"); _xmlprint(bp, ep->child, in+indent); Bprint(bp, "%*s</%s>\n", in, "", ep->name); } else{ if(ep->pcdata){ Bprint(bp, ">\n%*s", in+indent, ""); prval(bp, ep->pcdata); Bprint(bp, "\n%*s</%s>\n", in, "", ep->name); } else Bprint(bp, "/>\n"); } } } void xmlprint(Xml *xp, int fd) { Biobuf bout; Binit(&bout, fd, OWRITE); if(xp->doctype){ Bprint(&bout, "<?xml version='1.0' encoding='utf-8'?>\n"); Bprint(&bout, "<!DOCTYPE %s>\n", xp->doctype); } else Bprint(&bout, "<?xml version='1.0' encoding='utf-8' standalone='yes'?>\n"); _xmlprint(&bout, xp->root, 0); Bterm(&bout); }