/** Prints the specified node, recursively. */
  public void print(Node node) {

    // is there anything to do?
    if (node == null) {
      return;
    }

    int type = node.getNodeType();
    switch (type) {
        // print document
      case Node.DOCUMENT_NODE:
        {
          if (!canonical) {
            String Encoding = getWriterEncoding();
            if (Encoding.equalsIgnoreCase("DEFAULT")) Encoding = "UTF-8";
            else if (Encoding.equalsIgnoreCase("Unicode")) Encoding = "UTF-16";
            else Encoding = MIME2Java.reverse(Encoding);

            out.println("<?xml version=\"1.0\" encoding=\"" + Encoding + "\"?>");
          }
          print(((Document) node).getDocumentElement());
          out.flush();
          break;
        }

        // print element with attributes
      case Node.ELEMENT_NODE:
        {
          out.print('<');
          if (this.qualifiedNames) {
            out.print(node.getNodeName());
          } else {
            out.print(node.getLocalName());
          }
          Attr attrs[] = sortAttributes(node.getAttributes());
          for (int i = 0; i < attrs.length; i++) {
            Attr attr = attrs[i];
            out.print(' ');
            if (this.qualifiedNames) {
              out.print(attr.getNodeName());
            } else {
              out.print(attr.getLocalName());
            }

            out.print("=\"");
            out.print(normalize(attr.getNodeValue()));
            out.print('"');
          }
          out.print('>');
          NodeList children = node.getChildNodes();
          if (children != null) {
            int len = children.getLength();
            for (int i = 0; i < len; i++) {
              print(children.item(i));
            }
          }
          break;
        }

        // handle entity reference nodes
      case Node.ENTITY_REFERENCE_NODE:
        {
          if (canonical) {
            NodeList children = node.getChildNodes();
            if (children != null) {
              int len = children.getLength();
              for (int i = 0; i < len; i++) {
                print(children.item(i));
              }
            }
          } else {
            out.print('&');
            if (this.qualifiedNames) {
              out.print(node.getNodeName());
            } else {
              out.print(node.getLocalName());
            }
            out.print(';');
          }
          break;
        }

        // print cdata sections
      case Node.CDATA_SECTION_NODE:
        {
          if (canonical) {
            out.print(normalize(node.getNodeValue()));
          } else {
            out.print("<![CDATA[");
            out.print(node.getNodeValue());
            out.print("]]>");
          }
          break;
        }

        // print text
      case Node.TEXT_NODE:
        {
          out.print(normalize(node.getNodeValue()));
          break;
        }

        // print processing instruction
      case Node.PROCESSING_INSTRUCTION_NODE:
        {
          out.print("<?");
          if (this.qualifiedNames) {
            out.print(node.getNodeName());
          } else {
            out.print(node.getLocalName());
          }

          String data = node.getNodeValue();
          if (data != null && data.length() > 0) {
            out.print(' ');
            out.print(data);
          }
          out.print("?>");
          break;
        }
    }

    if (type == Node.ELEMENT_NODE) {
      out.print("</");
      if (this.qualifiedNames) {
        out.print(node.getNodeName());
      } else {
        out.print(node.getLocalName());
      }
      out.print('>');
    }

    out.flush();
  } // print(Node)
 public static void setWriterEncoding(String encoding) {
   if (encoding.equalsIgnoreCase("DEFAULT")) PRINTWRITER_ENCODING = "UTF8";
   else if (encoding.equalsIgnoreCase("UTF-16")) PRINTWRITER_ENCODING = "Unicode";
   else PRINTWRITER_ENCODING = MIME2Java.convert(encoding);
 } // setWriterEncoding