LoginSignup
0
0

JavaでXML風のテキストを整形するツール

Posted at

JavaでXML風のテキストを整形するツール

1行で記載されたXML風のテキストを整形する

やりたいことのイメージ

1行で記載されたXMLを整形する。

<xml><tagA><tagA-A>aaa</tagA-A><tagA-B>aaa</tagA-B></tagA><tagB-A>aaa</tagB-A><tagB-B>aaa</tagB-B><tagB><tagB-A>aaa</tagB-A><tagB-B>aaa</tagB-B></tagB>

これを↓のように整形する。

<xml>
    <tagA>
        <tagA-A>aaa</tagA-A>
        <tagA-B>aaa</tagA-B>
    </tagA>
    <tagB-A>aaa</tagB-A>
    <tagB-B>aaa</tagB-B>
    <tagB>
        <tagB-A>aaa</tagB-A>
        <tagB-B>aaa</tagB-B>
    </tagB>

前提

XMLとしてのチェックはしていない。
XMLの不備は無視してそのまま整形している。

ソース

・batファイル(do.bat)

echo off
cd ./
javac IoTest.java
java IoTest
pause

・Javaファイル(IoTest.java)

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

class IoTest {

	// 外部ファイルパス
	private static final String INPUT_PATH = "./file/inputXml/";
	private static final String OUTPUT_PATH = "./file/outputXml/";

	// XML定数
	private static final String XML_START = "<";
	private static final String XML_END = ">";
	private static final String XML_SHIME = "/";
	private static final String XML_KBN_OPEN = "XML_OPEN";
	private static final String XML_KBN_CLOSE = "XML_CLOSE";
	private static final String XML_INDENT = "    ";
	private static final String XML_KAIGYO = "\r\n";

	// 改行、インデント区分
	private static final String KI_KBN_ON_PLUS = "KI_000";
	private static final String KI_KBN_ON_NON = "KI_001";
	private static final String KI_KBN_OFF_NON = "KI_002";
	private static final String KI_KBN_ON_MINUS = "KI_003";

	public static void main(String[] args) {
		try {
			// すでに出力済みのファイルを削除する。
			deleteFile();

			// INPUT_PATHに格納されているファイル分繰り返し処理をする
			File file = new File(INPUT_PATH);
			File files[] = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				execute(files[i].getName());
			}
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public static void deleteFile() throws Exception {
		try {
			File file = new File(OUTPUT_PATH);
			File files[] = file.listFiles();

			for (File work : files) {
				Path p = Paths.get(OUTPUT_PATH + work.getName());
				Files.delete(p);
			}

		} catch (Exception e) {
			System.out.println(e);
			throw e;
		}
	}

	public static void execute(String fileName) throws Exception {
		try {
			Path path = Paths.get(INPUT_PATH + fileName);
			List<String> list = Files.readAllLines(path);
			String xmlStr = convertXml(list.get(0));
			outputXmlFile(fileName, xmlStr);
		} catch (Exception e) {
			System.out.println(e);
			throw e;
		}
	}

	public static void outputXmlFile(String fileName, String fileValue) throws Exception {
		try {
			FileWriter fw = new FileWriter(OUTPUT_PATH + fileName);
			PrintWriter pw = new PrintWriter(new BufferedWriter(fw));

			pw.println(fileValue);

			pw.close();
		} catch (Exception e) {
			System.out.println(e);
			throw e;
		}
	}

	public static String convertXml(String xmlStr) throws Exception {
		String result = "";

		try {
			// 文字列分繰り返し処理をする
			String[] workStr = xmlStr.split("");
			String[] tagInfo = {"", "", "", ""};
			int indentCount = 0;
			String kiKbn= "";
			boolean kaigyoIndentAddFlag = false;
			for (int i = 0;i < workStr.length; i++) {
				String work = workStr[i];

				// 改行、インデント設定を行う。
				if (kaigyoIndentAddFlag) {
					result = addKaigyouIndent(result, kiKbn, indentCount);
					kaigyoIndentAddFlag = false;
				}

				if (XML_START.equals(work)) {
					// 開始タグの場合、タグ情報の設定を行う。
					tagInfo = analyzeXmlTagInfo(workStr, i);
				}
				if (XML_END.equals(work)) {
					// 終了タグの場合、改行、インデント設定を行う。
					kiKbn = checkKaigyouIndent(tagInfo);
					indentCount = checkIndentCount(kiKbn, indentCount);
					kaigyoIndentAddFlag = true;
				}

				result = result + work;
			}
		} catch (Exception e) {
			System.out.println(e);
			throw e;
		}

		return result;
	}

	public static String getNextStr(String[] arrayStr, int nowIndex) throws Exception {
		String result = "";

		int size = arrayStr.length;
		int nextIndex = nowIndex + 1;

		if (size > nextIndex) {
			result = arrayStr[nextIndex];
		}

		return result;
	}

	public static String[] analyzeXmlTagInfo(String[] arrayStr, int nowIndex) throws Exception {
		String[] result = {"", "", "", ""};
		String nowXmlTagInfo = "";
		String nowXmlTagKbn = XML_KBN_OPEN;
		String nextXmlTagInfo = "";
		String nextXmlTagKbn = XML_KBN_OPEN;

		int nextTagIndex = 0;

		// 現在タグの情報を設定する。
		for (int i = nowIndex; i < arrayStr.length; i++) {
			String work = arrayStr[i];

			if (XML_START.equals(work)) {
				// 開始タグはスキップする。
				continue;
			}
			if (XML_SHIME.equals(work)) {
				// "/"の場合はタグ区分を変更する。
				nowXmlTagKbn = XML_KBN_CLOSE;
				continue;
			}
			if (XML_END.equals(work)) {
				// 終了タグは次回タグのインデックスを設定して終了する。
				nextTagIndex = i + 1;
				break;
			}

			nowXmlTagInfo = nowXmlTagInfo + work;
		}

		// 次回タグの情報を設定する。
		boolean addFlag = false;
		for (int i = nextTagIndex; i < arrayStr.length; i++) {
			String work = arrayStr[i];

			if (XML_START.equals(work)) {
				// 開始タグを検知してからタグ情報を設定する。
				addFlag = true;
				continue;
			}
			if (XML_SHIME.equals(work)) {
				// "/"の場合はタグ区分を変更する。
				nextXmlTagKbn = XML_KBN_CLOSE;
				continue;
			}
			if (XML_END.equals(work)) {
				// 終了タグは終了する。
				break;
			}

			if (addFlag) {
				nextXmlTagInfo = nextXmlTagInfo + work;
			}
		}

		result[0] = nowXmlTagInfo;
		result[1] = nowXmlTagKbn;
		result[2] = nextXmlTagInfo;
		result[3] = nextXmlTagKbn;

		return result;
	}

	public static String checkKaigyouIndent(String[] tagInfo) throws Exception {
		String result = "";

		String nowXmlTagInfo = tagInfo[0];
		String nowXmlTagKbn = tagInfo[1];
		String nextXmlTagInfo = tagInfo[2];
		String nextXmlTagKbn = tagInfo[3];

		if (XML_KBN_OPEN.equals(nextXmlTagKbn)) {
			if (XML_KBN_OPEN.equals(nowXmlTagKbn)) {
				// 改行:する、インデント:増
				result = KI_KBN_ON_PLUS;
			} else {
				// 改行:する、インデント:無
				result = KI_KBN_ON_NON;
			}
		} else {
			if (XML_KBN_OPEN.equals(nowXmlTagKbn)) {
				// 改行:しない、インデント:無
				result = KI_KBN_OFF_NON;
			} else {
				// 改行:する、インデント:減
				result = KI_KBN_ON_MINUS;
			}
		}
		
		return result;
	}

	public static int checkIndentCount(String kiKbn, int nowIndentCount) throws Exception {
		int result = nowIndentCount;

		if (KI_KBN_ON_PLUS.equals(kiKbn)) {
			// 設定するインデントを増やす
			result++;
		} else if (KI_KBN_ON_MINUS.equals(kiKbn)) {
			// 設定するインデントを減らす
			result--;
		}

		return result;
	}

	public static String addKaigyouIndent(String nowStr, String kiKbn, int indentCount) throws Exception {
		String addStr = "";

		if (KI_KBN_OFF_NON.equals(kiKbn)) {
			// 改行しない場合はそのまま返却
			return nowStr;
		}

		// 改行設定
		addStr = XML_KAIGYO;

		// インデント設定
		for (int i = 0; i < indentCount; i++) {
			addStr = addStr + XML_INDENT;
		}

		return nowStr + addStr;
	}
}

使い方

任意のディレクトリに上記のバッチファイルとJavaファイルを格納し、
以下の構成のディレクトリを作成する。

file
├─inputXml
└─outputXml
  • inputXml
    変換したいファイルを格納する。
  • outputXml
    バッチを実行すると変換されたファイルが作成される。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0