| 
1466
 | 
     1 package goodjava.xml;
 | 
| 
 | 
     2 
 | 
| 
 | 
     3 import java.util.Map;
 | 
| 
 | 
     4 
 | 
| 
 | 
     5 
 | 
| 
 | 
     6 public final class XmlElement {
 | 
| 
 | 
     7 	public final String name;
 | 
| 
 | 
     8 	public final Map<String,String> attributes;
 | 
| 
1790
 | 
     9 	private Object content = null;
 | 
| 
1791
 | 
    10 	private XmlElement parent = null;
 | 
| 
1466
 | 
    11 
 | 
| 
1468
 | 
    12 	public XmlElement(String name,Map<String,String> attributes) {
 | 
| 
 | 
    13 		this.name = name;
 | 
| 
 | 
    14 		this.attributes = attributes;
 | 
| 
 | 
    15 		this.content = null;
 | 
| 
 | 
    16 	}
 | 
| 
 | 
    17 
 | 
| 
1791
 | 
    18 	public XmlElement getParent() {
 | 
| 
 | 
    19 		return parent;
 | 
| 
 | 
    20 	}
 | 
| 
 | 
    21 
 | 
| 
1790
 | 
    22 	public Object getContent() {
 | 
| 
 | 
    23 		return content;
 | 
| 
 | 
    24 	}
 | 
| 
 | 
    25 
 | 
| 
 | 
    26 	public void removeContent() {
 | 
| 
 | 
    27 		content = null;
 | 
| 
 | 
    28 	}
 | 
| 
 | 
    29 
 | 
| 
 | 
    30 	public void setContent(String content) {
 | 
| 
1468
 | 
    31 		if( content == null )
 | 
| 
1810
 | 
    32 			throw new IllegalArgumentException("content of '"+name+"' can't be null");
 | 
| 
1466
 | 
    33 		this.content = content;
 | 
| 
 | 
    34 	}
 | 
| 
 | 
    35 
 | 
| 
1790
 | 
    36 	public void setContent(XmlElement[] content) {
 | 
| 
1468
 | 
    37 		if( content == null )
 | 
| 
1810
 | 
    38 			throw new IllegalArgumentException("content of '"+name+"' can't be null");
 | 
| 
1466
 | 
    39 		this.content = content;
 | 
| 
1791
 | 
    40 		for( XmlElement el : content ) {
 | 
| 
 | 
    41 			el.parent = this;
 | 
| 
 | 
    42 		}
 | 
| 
1466
 | 
    43 	}
 | 
| 
 | 
    44 
 | 
| 
1790
 | 
    45 	@Override public String toString() {
 | 
| 
1466
 | 
    46 		StringBuilder sb = new StringBuilder();
 | 
| 
 | 
    47 		toString(sb,0);
 | 
| 
 | 
    48 		return sb.toString();
 | 
| 
 | 
    49 	}
 | 
| 
 | 
    50 
 | 
| 
1790
 | 
    51 	void toString(StringBuilder sb,int indented) {
 | 
| 
1466
 | 
    52 		indent(sb,indented);
 | 
| 
 | 
    53 		sb.append( '<' );
 | 
| 
 | 
    54 		sb.append( name );
 | 
| 
 | 
    55 		for( Map.Entry<String,String> attribute : attributes.entrySet() ) {
 | 
| 
 | 
    56 			sb.append( ' ' );
 | 
| 
 | 
    57 			sb.append( attribute.getKey() );
 | 
| 
 | 
    58 			sb.append( "=\"" );
 | 
| 
1793
 | 
    59 			sb.append( encodeAttr(attribute.getValue()) );
 | 
| 
1466
 | 
    60 			sb.append( '"' );
 | 
| 
 | 
    61 		}
 | 
| 
1468
 | 
    62 		if( content == null ) {
 | 
| 
 | 
    63 			sb.append( "/>\n" );
 | 
| 
 | 
    64 		} else if( content instanceof String ) {
 | 
| 
 | 
    65 			sb.append( '>' );
 | 
| 
1466
 | 
    66 			String s = (String)content;
 | 
| 
1468
 | 
    67 			sb.append( encode(s) );
 | 
| 
 | 
    68 			closeTag(sb,name);
 | 
| 
1467
 | 
    69 		} else {
 | 
| 
1468
 | 
    70 			sb.append( '>' );
 | 
| 
1466
 | 
    71 			XmlElement[] elements = (XmlElement[])content;
 | 
| 
 | 
    72 			sb.append( '\n' );
 | 
| 
 | 
    73 			for( XmlElement element : elements ) {
 | 
| 
 | 
    74 				element.toString(sb,indented+1);
 | 
| 
 | 
    75 			}
 | 
| 
 | 
    76 			indent(sb,indented);
 | 
| 
1468
 | 
    77 			closeTag(sb,name);
 | 
| 
1467
 | 
    78 		}
 | 
| 
1468
 | 
    79 	}
 | 
| 
 | 
    80 
 | 
| 
 | 
    81 	private static void closeTag(StringBuilder sb,String name) {
 | 
| 
1466
 | 
    82 		sb.append( "</" );
 | 
| 
 | 
    83 		sb.append( name );
 | 
| 
 | 
    84 		sb.append( ">\n" );
 | 
| 
 | 
    85 	}
 | 
| 
 | 
    86 
 | 
| 
1467
 | 
    87 	private static void indent(StringBuilder sb,int indented) {
 | 
| 
1466
 | 
    88 		for( int i=0; i<indented; i++ ) {
 | 
| 
 | 
    89 			sb.append('\t');
 | 
| 
 | 
    90 		}
 | 
| 
 | 
    91 	}
 | 
| 
 | 
    92 
 | 
| 
1469
 | 
    93 	public static String encode(String s) {
 | 
| 
1468
 | 
    94 		final char[] a = s.toCharArray();
 | 
| 
 | 
    95 		StringBuilder buf = new StringBuilder();
 | 
| 
1469
 | 
    96 		for( char c : a ) {
 | 
| 
1468
 | 
    97 			switch(c) {
 | 
| 
 | 
    98 			case '&':
 | 
| 
 | 
    99 				buf.append("&");
 | 
| 
 | 
   100 				break;
 | 
| 
 | 
   101 			case '<':
 | 
| 
 | 
   102 				buf.append("<");
 | 
| 
 | 
   103 				break;
 | 
| 
 | 
   104 			case '>':
 | 
| 
 | 
   105 				buf.append(">");
 | 
| 
 | 
   106 				break;
 | 
| 
 | 
   107 			case '"':
 | 
| 
 | 
   108 				buf.append(""");
 | 
| 
 | 
   109 				break;
 | 
| 
1469
 | 
   110 			case '\'':
 | 
| 
 | 
   111 				buf.append("'");
 | 
| 
 | 
   112 				break;
 | 
| 
1793
 | 
   113 			default:
 | 
| 
 | 
   114 				buf.append(c);
 | 
| 
 | 
   115 			}
 | 
| 
 | 
   116 		}
 | 
| 
 | 
   117 		return buf.toString();
 | 
| 
 | 
   118 	}
 | 
| 
 | 
   119 
 | 
| 
 | 
   120 	public static String encodeAttr(String s) {
 | 
| 
 | 
   121 		final char[] a = s.toCharArray();
 | 
| 
 | 
   122 		StringBuilder buf = new StringBuilder();
 | 
| 
 | 
   123 		for( char c : a ) {
 | 
| 
 | 
   124 			switch(c) {
 | 
| 
 | 
   125 			case '&':
 | 
| 
 | 
   126 				buf.append("&");
 | 
| 
 | 
   127 				break;
 | 
| 
 | 
   128 			case '<':
 | 
| 
 | 
   129 				buf.append("<");
 | 
| 
 | 
   130 				break;
 | 
| 
 | 
   131 			case '>':
 | 
| 
 | 
   132 				buf.append(">");
 | 
| 
 | 
   133 				break;
 | 
| 
 | 
   134 			case '"':
 | 
| 
 | 
   135 				buf.append(""");
 | 
| 
 | 
   136 				break;
 | 
| 
 | 
   137 			case '\'':
 | 
| 
 | 
   138 				buf.append("'");
 | 
| 
 | 
   139 				break;
 | 
| 
1790
 | 
   140 			case '\n':
 | 
| 
 | 
   141 				buf.append("
");
 | 
| 
 | 
   142 				break;
 | 
| 
 | 
   143 			case '\r':
 | 
| 
 | 
   144 				buf.append("
");
 | 
| 
 | 
   145 				break;
 | 
| 
1468
 | 
   146 			default:
 | 
| 
 | 
   147 				buf.append(c);
 | 
| 
 | 
   148 			}
 | 
| 
 | 
   149 		}
 | 
| 
 | 
   150 		return buf.toString();
 | 
| 
 | 
   151 	}
 | 
| 
 | 
   152 
 | 
| 
1466
 | 
   153 }
 |