code: private static void handleWsRec(Node n, boolean normalize) {
          if (n instanceof CharacterData || n instanceof ProcessingInstruction) {
              String s = n.getNodeValue().trim();
              if (normalize) {
                  s = normalize(s);
              }
              n.setNodeValue(s);
          }
          List<Node> toRemove = new LinkedList<Node>();
          for (Node child : new IterableNodeList(n.getChildNodes())) {
              handleWsRec(child, normalize);
              if (!(n instanceof Attr)
                  && (child instanceof Text || child instanceof CDATASection)
                  && child.getNodeValue().length() == 0) {
                  toRemove.add(child);
              }
          }
          for (Node child : toRemove) {
              n.removeChild(child);
          }
          NamedNodeMap attrs = n.getAttributes();
          if (attrs != null) {
              final int len = attrs.getLength();
              for (int i = 0; i < len; i++) {
                  handleWsRec(attrs.item(i), normalize);
              }
          }
      }
docs: Trims textual content of this node, removes empty text and
  CDATA children, recurses into its child nodes.
  @param normalize whether to normalize whitespace as well