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
バッチを実行すると変換されたファイルが作成される。