import java.io.*;
import java.net.URL;
import java.security.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;

import com.sun.org.apache.xerces.internal.parsers.DOMParser;
/**
 * xmlを読み込む用のクラス
 * @author 珠あき
 *
 */
public class XmlReaderOfDOM {
	Document doc=null;
	private static int tab=1;
	public static void main(String args[]) {
		XmlReaderOfDOM d;
		String str;
		try{
			if(args.length>0){
				if(args.length>1){
					String stab=args[1];
					int i=Integer.parseInt(stab);
					if(i>-1){
						tab=i;
					}
				}
				str=args[0];
				try {
					d = new XmlReaderOfDOM(str);
					d.printAllDocument();
				} catch (SAXException e) {
					System.err.println("xmlの構文エラー");
	//				e.printStackTrace();
				} catch (IOException e) {
	//				e.printStackTrace();
				}
			}else{
				System.err.println("ファイルが指定されていません。");
			}
		}catch(NumberFormatException e){
			System.err.println("第2引数が整数型ではありません。");
		}
	}
	/**
	 * Documentとしてデータを返す。
	 * @return Document
	 */
	public Document getDocument(){
		return doc;
	}
	/**
	 * Elementとしてデータを返す。
	 * @return Element
	 */
	public Element getRootElement(){
		return doc.getDocumentElement();
	}
	/**
	 * 
	 * @param url
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 * @throws FileNotFoundException
	 * @throws NullPointerException
	 * @throws AccessControlException
	 */
	public XmlReaderOfDOM(String url) throws SAXException,FileNotFoundException,IOException,NullPointerException,AccessControlException{
		DOMParser parser = new DOMParser();
		parser.parse(url);
		doc = parser.getDocument();
	}
	/**
	 * 
	 * @param url
	 * xmlファイルのURL
	 * @throws SAXException
	 * xmlの構文が異常な際のエラー
	 * @throws FileNotFoundException
	 * ファイルが無い場合のエラー
	 * @throws NullPointerException
	 * urlの文字がnull時のエラー
	 * @throws IOException 
	 */
	public XmlReaderOfDOM(URL url) throws SAXException,NullPointerException,FileNotFoundException, IOException{
		InputStream fin = url.openConnection().getInputStream();
		DOMParser parser = new DOMParser();
		parser.parse(new InputSource(fin));
		doc = parser.getDocument();
	}
	/**
	 * 全ての属性や要素を元の形式に近い形で出力する。
	 * @throws NullPointerException
	 */
	public void printAllDocument()throws NullPointerException{
		if(doc!=null){
			printDocument(doc.getFirstChild(),0);
		}
	}
	/**
	 * 指定した要素以下の値を出力する。
	 * printAllDocument用の回帰プログラム
	 */
	private void printDocument(Node elem, int depth) {
		String s="";
		for (int i = 0; i < depth; i++) {
			s+=" ";
		}
		int type=elem.getNodeType();
		String name = elem.getNodeName();
		if(type==3){
			if(charcheck(elem.getNodeValue()).length()>0){
				System.out.println(s+elem.getNodeValue());
			}
		}else if(type==1){
			System.out.print(s+"<"+name);
			NamedNodeMap e=elem.getAttributes();
			for(int i=0;e!=null&&i<e.getLength();i++){
				System.out.print(" "+e.item(i).getNodeName()+"='"+e.item(i).getNodeValue()+"'");
			}
			NodeList list = elem.getChildNodes();
			int n = list.getLength();
			if(n==0){
				System.out.print(" />\n");
			}else{
				System.out.print(" >\n");
				for (int i = 0; i < n; i++) {
					Node child = list.item(i);
					printDocument(child, depth + tab);
				}
				System.out.print(s+"</"+name+">\n");
			}
			
		}
	}
	/**
	 * 文字の不必要な値を除去する。
	 * printDocument専用
	 * @param str
	 * @return
	 */
	private String charcheck(String str){
		StringBuffer _str=new StringBuffer();
		for(int i=0;i<str.length();i++){
			if(Character.isLetterOrDigit(str.charAt(i))){
				_str.append(str.charAt(i));
			}
		}
		return _str.toString();
	}
}
