27
27
import javax .xml .xpath .XPathFactory ;
28
28
import javax .xml .xpath .XPathFactoryConfigurationException ;
29
29
import org .w3c .dom .Document ;
30
+ import org .w3c .dom .Element ;
31
+ import org .w3c .dom .NamedNodeMap ;
32
+ import org .w3c .dom .Node ;
30
33
import org .w3c .dom .NodeList ;
31
34
import org .xml .sax .InputSource ;
32
35
import org .xml .sax .SAXException ;
@@ -40,6 +43,20 @@ public class XMLPrettyPrinter {
40
43
41
44
public static int IDENT_AMOUNT = 4 ;
42
45
46
+ /**
47
+ * This function formats all tags (and their children) which are marked with
48
+ * the autoformat="true" attribute and removes this attribute.
49
+ *
50
+ * @param input
51
+ * @return
52
+ * @throws TransformerConfigurationException
53
+ * @throws ParserConfigurationException
54
+ * @throws SAXException
55
+ * @throws IOException
56
+ * @throws TransformerException
57
+ * @throws XPathExpressionException
58
+ * @throws XPathFactoryConfigurationException
59
+ */
43
60
public static String prettyPrintXML (String input ) throws TransformerConfigurationException ,
44
61
ParserConfigurationException , SAXException , IOException , TransformerException , XPathExpressionException ,
45
62
XPathFactoryConfigurationException {
@@ -50,24 +67,25 @@ public static String prettyPrintXML(String input) throws TransformerConfiguratio
50
67
StreamResult result = new StreamResult (new StringWriter ());
51
68
Document doc = DocumentBuilderFactory .newInstance ().newDocumentBuilder ()
52
69
.parse (new InputSource (new StringReader (input )));
53
- XPathExpression xpath = XPathFactory .newInstance ().newXPath ().compile ("//*[count(./*) = 0]" );
54
70
XPathExpression xpathDepth = XPathFactory .newInstance ().newXPath ().compile ("count(ancestor-or-self::*)" );
55
-
56
- NodeList textNodes = (NodeList ) xpath .evaluate (doc , XPathConstants .NODESET );
57
-
71
+ XPathExpression toBeFormatted = XPathFactory .newInstance ().newXPath ().compile ("//*[@autoformat = \' true\' ]/*" );
72
+ NodeList textNodes = (NodeList ) toBeFormatted .evaluate (doc , XPathConstants .NODESET );
58
73
for (int i = 0 ; i < textNodes .getLength (); i ++) {
59
- String content = textNodes .item (i ).getTextContent ();
74
+ Node node = textNodes .item (i );
75
+ String content = node .getTextContent ();
60
76
double doubleDepth = (Double ) xpathDepth .evaluate (textNodes .item (i ), XPathConstants .NUMBER );
61
77
int depth = (int ) doubleDepth ;
62
78
String emptyString = createEmptyString (depth );
63
79
String newContent = content .replaceAll ("\n " , ("\n " + emptyString ));
64
- if (newContent .length () > content .length ()) {
80
+ if (newContent .length () > content .length ()
81
+ && newContent .substring (newContent .length () - IDENT_AMOUNT , newContent .length ()).trim ().equals ("" )) {
65
82
newContent = newContent .substring (0 , newContent .length () - IDENT_AMOUNT );
66
83
}
67
- textNodes .item (i ).setTextContent (newContent );
84
+ node .setTextContent (newContent );
85
+ Element element = (Element ) node .getParentNode ();
86
+ element .removeAttribute ("autoformat" );
68
87
69
88
}
70
-
71
89
DOMSource source = new DOMSource (doc );
72
90
transformer .transform (source , result );
73
91
return result .getWriter ().toString ();
0 commit comments