数学、電気の勉強始めました!プログラムにも挑戦しています!|ω・)ノ

ねごとめも背景

# ねごとめも

# カウンター

# プロフィール

negotoy

Author:negotoy
電気の勉強始めました!
テキストエディタを使ってプログラミングに挑戦中。
fc2 ブログに公開しているテンプレート等は、自由にカスタマイズして、ご活用ください。
プログラム実行の前に必ずコードの確認をお願いします。

# 最新記事

# カレンダー

05 | 2013/06 | 07
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -

# スポンサードリンク

{ <pre></pre> タグ版のテキストエディタ作成しました }

今回は2つの CSV ファイルの列値を比較して同じ値であればその行の任意の列データを流し込むテスト。
例:
A csv ファイルに商品 ID ( 1234 ) の行データが存在する。
商品 ID ( 1234 ) 行の 20 列の値に 消費税込の価格のデータがある。

A csv ファイルを編集した B csv ファイルに A ファイルと同じ商品 ID ( 1234 ) の編集済みの行データがある。
その 10 列の値に消費税込みの価格データがある。

消費税が上がり A csv ファイルの消費税込みの価格が変更される。
B ファイルの消費税込み価格データ ( 10 列 ) を
A csv ファイルの消費税込み価格データ ( 20 列 ) に書き換えるもの。
よくわからない。('A`)

消費税が上がった時の為に作成したテストプログラム。
こういうの、 Libreoffice で出来たりするのかな。
マ、マクロ??とか使って??

この java プログラムが実際、使えるかどうかは、その日が来るまでわからない。
*試される場合は、実行する前に CSV ファイルのバックアップを取ってください。
*読み込める csv ファイルはカンマ区切りの csv ファイルです。
*出力ファイルのエンコード utf-8
*入力ファイルのエンコード utf-8 以外

JTextField に ディレクトリのパスを入力すると、
そのディレクトリをルートにしたファイルチューザーが表示されます。
”root reset” ボタンでルート初期化。
”古いファイルの選択” ボタンで書き換え csv ファイルの読み込み。
”新しいファイルの選択” ボタンで入れ換える csv ファイルの読み込み。
JComboBox で比較する ID セルの選択、置き換え、書き換え、セルの選択。
”実行” ボタンで指定セルの書き換え。
コンパイルすると警告がでます。
”古いファイルの選択” で選択したファイル名で出力するので、必ずバックアップをっ!
確認ダイアログも無く、迷いなく上書きします!\(^o^)/

■ SetPrice.java 実行結果

java csv 列値入れ替え

■ SetPrice.java


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.filechooser.FileNameExtensionFilter;

public class SetPrice extends JFrame
{
	private static SetPrice price;
	private JTextField oldDir,newDir;
	private JButton selectOLD,selectNEW;
	private JTextArea result;
	private CSV oldCSV,newCSV;
	private String[][] oldData,newData;
	private DefaultComboBoxModel oldIdComboBoxModel,newIdComboBoxModel,oldColComboBoxModel,newColComboBoxModel;
	private JComboBox oldIdCombo,newIdCombo,oldColCombo,newColCombo;
	private MyFileOpenListener oldFileOpenListener,newFileOpenListener;

	private class CSV
	{
		final void setData(String[][] data){ csv=null; csv=data; }

		final void write(String fileName) throws FileNotFoundException, IOException
		{
			try(BufferedWriter output=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName),"utf-8")))
			{
				StringBuffer result=new StringBuffer();
				for(int i=0;i<csv.length;i++)
				{
					for(int j=0;j<csv[i].length;j++)
					{
						String comma="\",\"";
						String quot=(j==0)?"\"":"";
						if(j==(csv[i].length-1)){ comma="\"\n"; }
						result.append(quot);
						result.append(csv[i][j]);
						result.append(comma);
					}
				}
				output.write(result.toString().trim());
				output.close();
			}
		}

		private String[][] csv;
		final String[][] fgetcsv(String fileName,String encode) throws FileNotFoundException, IOException
		{
			csv=null;
			try(BufferedReader input=new BufferedReader(new InputStreamReader(new FileInputStream(fileName),encode)))
			{
				ArrayList<ArrayList> rows=new ArrayList<>();
				ArrayList<String> cols=new ArrayList<>();
				StringBuffer str=new StringBuffer();
				int rowsIndex=0;
				int colsIndex=0;
				int colsMax=0;
				boolean group=false;
				int ch;
				char prev=',';
				boolean space=false;
				while((ch=input.read())!=-1)
				{
					char _char=(char)ch;
					if(!group)
					{
						switch(_char)
						{
							case '\r' : break;

							case '"':
									if(prev==',')
									{
										group=true;
									}
									str.append(_char);
									prev=_char;
							break;

							case ',':
									cols.add(colsIndex,str.toString());
									colsIndex++;
									str=new StringBuffer();
									prev=_char;
							break;

							case '\n':
									cols.add(colsIndex,str.toString());
									rows.add(rowsIndex,cols);
									rowsIndex++;
									colsMax=(colsMax<cols.size())? cols.size():colsMax;
									colsIndex=0;
									cols=new ArrayList<>();
									str=new StringBuffer();
									//prev=_char;
									prev=',';
							break;

							default:
									str.append(_char);
									prev=_char;
							break;
						}
					}
					else
					{
						switch(_char)
						{
							case '\r' : break;

							case ',':
									if(str.length()==1)
									{
										str.append(_char);
									}
									else if(prev=='"')
									{
										group=false;
										cols.add(colsIndex,str.toString());
										colsIndex++;
										str=new StringBuffer();
									}
									else
									{
										str.append(_char);
									}
									prev=_char;
									space=false;
							break;

							case '\n':
									if(str.length()==1)
									{
										str.append(_char);
										prev=_char;
									}
									else if(prev=='"'&&!space)
									{
										group=false;
										cols.add(colsIndex,str.toString());
										rows.add(rowsIndex,cols);
										rowsIndex++;
										colsMax=(colsMax<cols.size())? cols.size():colsMax;
										colsIndex=0;
										cols=new ArrayList<>();
										str=new StringBuffer();
										prev=',';
									}
									else
									{
										str.append(_char);
										prev=_char;
									}
							break;

							case ' ': str.append(_char); space=true; break;
							case '\t': str.append(_char); space=true; break;
							case ' ': str.append(_char); space=true; break;

							default:
									str.append(_char);
									prev=_char;
									space=false;
							break;
						}
					}
				}
				if(colsIndex!=0||str.length()!=0)
				{
					cols.add(colsIndex,str.toString());
					rows.add(rowsIndex,cols);
					colsMax=(colsMax<cols.size())? cols.size():colsMax;
				}
				csv=new String[rows.size()][colsMax];
				for(int i=0;i<csv.length;i++)
				{
					for(int j=0;j<csv[i].length;j++)
					{
						String result;
						try{ result=(String)rows.get(i).get(j); }catch(IndexOutOfBoundsException e){ result=""; }
						result=result.replaceAll("^[  \t]|\t|[  \t]+$","");
						try
						{
							if(result.indexOf("\"")==0&&result.lastIndexOf("\"")==(result.length()-1))
							{
								result=result.substring(result.indexOf("\"")+1,result.lastIndexOf("\""));
							}
							else if(result.indexOf("\"")==0)
							{
								result=result.substring(result.indexOf("\"")+1,result.length());
							}
							else
							{
								result=result;
							}
						}catch(StringIndexOutOfBoundsException e){}
						csv[i][j]=result;
					}
				}
				input.close();
			}
			return csv;
		}
	}

	private class MyFileOpenListener implements ActionListener
	{
		private String prevDir="";
		private String nextDir="";
		JFileChooser filechooser=null;

		public void setDir(String dir)
		{
			prevDir=dir;
			nextDir=dir;
		}
		@Override
		public void actionPerformed(ActionEvent e)
		{
			result.setText("");
			prevDir=("oldFile".equals(e.getActionCommand()))? oldDir.getText().trim() : newDir.getText().trim();
			String currentDir=("".equals(nextDir)) ? prevDir : nextDir;
			File dir = new File(currentDir);
			//if(filechooser==null)
			//{
				filechooser=new JFileChooser(dir);
				filechooser.setDialogTitle("CSVファイルの選択");
				FileNameExtensionFilter filefilter=new FileNameExtensionFilter(".csv file","csv");
				filechooser.setFileFilter(filefilter);
			//}
			int selected=filechooser.showOpenDialog(price);
			if(selected==JFileChooser.APPROVE_OPTION)
			{
				File file=filechooser.getSelectedFile();
				String fileName=file.getName();
				if(fileName.endsWith(".csv"))
				{
					nextDir=String.valueOf(filechooser.getCurrentDirectory());
					fileName=String.valueOf(filechooser.getSelectedFile());
					switch(e.getActionCommand())
					{
						case "oldFile":
								selectOLD.setText(fileName);
								oldCSV=new CSV();
								try
								{
									oldData=oldCSV.fgetcsv(fileName,"utf-8");
								}
								catch(Exception ex){}
								oldIdComboBoxModel.removeAllElements();
								oldColComboBoxModel.removeAllElements();
								oldIdComboBoxModel.addElement("列番");
								oldColComboBoxModel.addElement("列番");
								for(int i=0;i<oldData[0].length;i++)
								{
									oldIdComboBoxModel.addElement(String.valueOf(i+1));
									oldColComboBoxModel.addElement(String.valueOf(i+1));
								}
						break;

						case "newFile":
								selectNEW.setText(fileName);
								newCSV=new CSV();
								try
								{
									newData=newCSV.fgetcsv(fileName,"JISAutoDetect");
								}
								catch(Exception ex){}
								newIdComboBoxModel.removeAllElements();
								newColComboBoxModel.removeAllElements();
								newIdComboBoxModel.addElement("列番");
								newColComboBoxModel.addElement("列番");
								for(int i=0;i<newData[0].length;i++)
								{
									newIdComboBoxModel.addElement(String.valueOf(i+1));
									newColComboBoxModel.addElement(String.valueOf(i+1));
								}
						break;
					}
				}
				else
				{
					alert("CSVファイルを選択してください。");
					switch(e.getActionCommand())
					{
						case "oldFile": selectOLD.setText("古いファイルの選択"); break;
						case "newFile": selectNEW.setText("新しいファイルの選択"); break;
					}
				}
			}
		}
	}
	private void alert(String str)
	{
		JLabel label=new JLabel(str);
		label.setFont(new Font("メイリオ",Font.PLAIN,12));
		label.setHorizontalAlignment(JLabel.CENTER);
		JOptionPane.showMessageDialog(this,label);
	}
	SetPrice()
	{
		super("csv 列値変更");
		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
		try
		{
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch(Exception ex)
		{
			System.out.println("Error");
		}
		setLayout(new BorderLayout());
		JPanel main=new JPanel();
		main.setLayout(new BoxLayout(main,BoxLayout.PAGE_AXIS));

		JPanel line_00=new JPanel();//label
		line_00.setLayout(new FlowLayout(FlowLayout.LEFT));
		JLabel label=new JLabel("【 値変更 】");

		Font font01=new Font("メイリオ",Font.BOLD,20);
		Font font02=new Font("メイリオ",Font.BOLD,12);
		line_00.add(label);
		label.setFont(font01);
		main.add(line_00);

		JPanel line_01=new JPanel();//label
		line_01.setLayout(new FlowLayout(FlowLayout.LEFT));
		label=new JLabel("■ 古 CSV ファイル  root:");
		label.setFont(font02);
		line_01.add(label);
		oldDir=new JTextField(54);
		line_01.add(oldDir);
		main.add(line_01);

		JPanel line_02=new JPanel();//button
		line_02.setLayout(new FlowLayout(FlowLayout.LEFT));
		selectOLD=new JButton("古いファイルの選択");
		selectOLD.setFont(font02);
		selectOLD.setPreferredSize(new Dimension(680,28));
		selectOLD.setActionCommand("oldFile");
		oldFileOpenListener=new MyFileOpenListener();
		selectOLD.addActionListener(oldFileOpenListener);
		line_02.add(selectOLD);
		main.add(line_02);

		JPanel line_03=new JPanel();//label
		line_03.setLayout(new FlowLayout(FlowLayout.LEFT));
		label=new JLabel("■ 新 CSV ファイル  root:");
		label.setFont(font02);
		line_03.add(label);
		newDir=new JTextField(54);
		line_03.add(newDir);
		main.add(line_03);

		JPanel line_04=new JPanel();//button
		line_04.setLayout(new FlowLayout(FlowLayout.LEFT));
		selectNEW=new JButton("新しいファイルの選択");
		selectNEW.setFont(font02);
		selectNEW.setPreferredSize(new Dimension(680,28));
		selectNEW.setActionCommand("newFile");
		newFileOpenListener=new MyFileOpenListener();
		selectNEW.addActionListener(newFileOpenListener);
		line_04.add(selectNEW);
		main.add(line_04);


		JPanel line_05=new JPanel();//label combobox combobox label combobox combobox label
		label =new JLabel("古列:");
		line_05.add(label);
		String[] oldComboData={"列番"};
		oldIdComboBoxModel=new DefaultComboBoxModel(oldComboData);
		oldIdCombo=new JComboBox(oldIdComboBoxModel);
		oldIdCombo.setPreferredSize(new Dimension(50,28));
		line_05.add(oldIdCombo);
		label=new JLabel("と 新列:");
		line_05.add(label);


		String[] newComboData={"列番"};
		newIdComboBoxModel=new DefaultComboBoxModel(newComboData);
		newIdCombo=new JComboBox(newIdComboBoxModel);
		newIdCombo.setPreferredSize(new Dimension(50,28));
		line_05.add(newIdCombo);
		label=new JLabel("を比較して同じ場合、");
		line_05.add(label);

		//line_05.add(Box.createRigidArea(new Dimension(50,5)));

		label =new JLabel("古列:");
		line_05.add(label);
		String[] oldColComboData={"列番"};
		oldColComboBoxModel=new DefaultComboBoxModel(oldColComboData);
		oldColCombo=new JComboBox(oldColComboBoxModel);
		oldColCombo.setPreferredSize(new Dimension(50,28));
		line_05.add(oldColCombo);
		label=new JLabel("と 新列:");
		line_05.add(label);


		String[] newColComboData={"列番"};
		newColComboBoxModel=new DefaultComboBoxModel(newColComboData);
		newColCombo=new JComboBox(newColComboBoxModel);
		newColCombo.setPreferredSize(new Dimension(50,28));
		line_05.add(newColCombo);
		label=new JLabel("の値を入れ替える");
		line_05.add(label);



		main.add(line_05);

		JPanel line_06=new JPanel();//button
		line_06.setLayout(new FlowLayout(FlowLayout.RIGHT));
		JButton reset=new JButton("root reset");
		reset.setFont(font02);
		reset.setPreferredSize(new Dimension(150,28));
		reset.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				oldFileOpenListener.setDir(oldDir.getText().trim());
				newFileOpenListener.setDir(newDir.getText().trim());
			}
		});
		line_06.add(reset);
		JButton run=new JButton("実行");
		run.setFont(font02);
		run.setPreferredSize(new Dimension(120,28));
		run.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				price.pack();
				if(!"古いファイルの選択".equals(selectOLD.getText())&&!"新しいファイルの選択".equals(selectNEW.getText()))
				{
					try
					{
						StringBuffer str=new StringBuffer();
						int oldIdNum=oldIdCombo.getSelectedIndex()-1;
						int newIdNum=newIdCombo.getSelectedIndex()-1;
						int oldColNum=oldColCombo.getSelectedIndex()-1;
						int newColNum=newColCombo.getSelectedIndex()-1;
						if(oldIdNum>-1&&newIdNum>-1&&oldColNum>-1&&newColNum>-1)
						{
							for(int i=0;i<newData.length;i++)
							{
								String newId=newData[i][newIdNum].trim();
								for(int j=0;j<oldData.length;j++)
								{
									String oldId=oldData[j][oldIdNum].trim();
									if(newId.equals(oldId))
									{
										if(!oldData[j][oldColNum].trim().equals(newData[i][newColNum].trim()))
										{
											oldData[j][oldColNum]=newData[i][newColNum].trim();
											str.append(oldId+"\n");
										}
									}
								}
							}
							oldCSV.setData(oldData);
							oldCSV.write(selectOLD.getText());
							str.append("値を変更しました。");
							result.setText(str.toString());
							//alert("値を変更しました。");
						}
						else
						{
							alert("列を選択してください。");
						}
					}
					catch(Exception ex){}
				}
				else
				{
					alert("csv ファイルを選択してください。");
				}
			}
		});
		line_06.add(run);
		main.add(line_06);

		result=new JTextArea(12,50);
		result.setFont(new Font("メイリオ",Font.PLAIN,14));
		JScrollPane scroll=new JScrollPane(result);
		main.add(scroll);

		add("North",main);
		int wid=(int)d.getWidth();
		int hei=(int)d.getHeight();
		setBounds((wid-700)/2,(hei-500)/2,700,500);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	public static void main(String[] args)
	{
		price=new SetPrice();
		price.pack();
	}
}

テスト(1) FlowLayout クラス, BorderLayout クラスを利用したレイアウト。
テスト(2) FlowLayout クラス, BorderLayout クラス, BoxLayout クラスを利用したレイアウト。
求める実行結果は部品が左詰め、上詰めでの表示。
ウインドウをリサイズした場合、部品の行位置が変更しないように配置。

テスト(1)では BorderLayout クラスを利用して部品をフレームの上部から配置。
フレームの下部にスペースが出来るようにする。
JPanel, ContentPane に BorderLayout を指定。
BorderLayout の North に部品を配置。
BorderLayout の Center に JPanel を配置。
Center に配置した JPanel に BorderLayout を設定。
その JPanel の North に部品を配置。
上記を繰り返して部品を改行レイアウトで配置する。

■ 改行レイアウト実行結果(1) BorderLayout クラス使用

改行レイアウト実行結果(1)

■ Layout_Test_00.java


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Layout_Test_00 extends JFrame
{
	Layout_Test_00()
	{
		super("改行レイアウトテスト(1)");
		Dimension d=Toolkit.getDefaultToolkit().getScreenSize();
		int wid=(int)d.getWidth();
		int hei=(int)d.getHeight();
		setLayout(new BorderLayout());
		try
		{
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex)
		{
			System.out.println("Error");
		}
		JPanel line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("一行目"));
		line.add(new JTextField(15));
		line.add(new JButton("send"));
		add("North",line);

		JPanel box_01=new JPanel();
		box_01.setLayout(new BorderLayout());
		line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("二行目"));
		line.add(new JTextField(15));
		line.add(new JButton("open"));
		box_01.add("North",line);
		add("Center",box_01);

		JPanel box_02=new JPanel();
		box_02.setLayout(new BorderLayout());
		line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("三行目"));
		line.add(new JTextField(15));
		line.add(new JButton("close"));
		box_02.add("North",line);
		box_01.add("Center",box_02);

		JPanel box_03=new JPanel();
		box_03.setLayout(new BorderLayout());
		line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("四行目"));
		line.add(new JTextField(15));
		line.add(new JButton("pack"));
		box_03.add("North",line);
		box_02.add("Center",box_03);

		JPanel box_04=new JPanel();
		box_04.setLayout(new BorderLayout());
		JScrollPane scroll=new JScrollPane(new JTextArea(5,60));
		box_04.add("North",scroll);
		box_03.add("Center",box_04);

		//setResizable(false);
		setBounds((wid-300)/2,(hei-400)/2,300,400);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}
	public static void main(String[] args)
	{
		Layout_Test_00 layout_Test_00=new Layout_Test_00();
		layout_Test_00.setVisible(true);
	}
}


テスト(2)では BoxLayout クラスを利用して部品をウインドウの上部から配置。
JFrame へ BorderLayout を設定。
最後に ContentPane の North に BoxLayout クラスで部品を配置した JPanel を配置して、
フレームの下部にスペースが出来るように改行レイアウトする。

テストした範囲では、 BoxLayout クラスを使用したほう ( テスト2 ) がコードがシンプルで配置しやすかった。

■ 改行レイアウト実行結果(2) BoxLayout クラス使用

改行レイアウト実行結果(2)

■ Layout_Test_01.java



import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Layout_Test_01 extends JFrame
{
	Layout_Test_01()
	{
		super("改行レイアウトテスト(2)");
		Dimension d=Toolkit.getDefaultToolkit().getScreenSize();
		int wid=(int)d.getWidth();
		int hei=(int)d.getHeight();
		setLayout(new BorderLayout());
		try
		{
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex)
		{
			System.out.println("Error");
		}
		setLayout(new BorderLayout());
		JPanel main=new JPanel();
		main.setLayout(new BoxLayout(main,BoxLayout.PAGE_AXIS));
		JPanel line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("一行目"));
		line.add(new JTextField(15));
		line.add(new JButton("send"));
		main.add(line);

		line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("二行目"));
		line.add(new JTextField(15));
		line.add(new JButton("open"));
		main.add(line);

		line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("三行目"));
		line.add(new JTextField(15));
		line.add(new JButton("close"));
		main.add(line);

		line=new JPanel();
		line.setLayout(new FlowLayout(FlowLayout.LEFT));
		line.add(new JLabel("四行目"));
		line.add(new JTextField(15));
		line.add(new JButton("pack"));
		main.add(line);

		JScrollPane scroll=new JScrollPane(new JTextArea(5,60));
		main.add(scroll);

		add("North",main);
		//setResizable(false);
		setBounds((wid-300)/2,(hei-400)/2,300,400);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}
	public static void main(String[] args)
	{
		Layout_Test_01 layout_Test_01=new Layout_Test_01();
		layout_Test_01.setVisible(true);
	}
}

今回は前回の javascript タグ削除テスト(2)の続き。
[ 修正箇所 ] 1) XML宣言, DTD宣言の記述を無視するように訂正。
2) textarea タグの内容を CDATA として出力。 ( textarea 内に textarea タグが存在する場合エラー )
3) html5 で定義されている空要素に、タグを閉じる記号 ( "/" ) 閉がなくても XML として出力。
その他、色々と修正。
textarea の HTML5 ドキュメントから XML ツリーを生成、文字列として出力まで。



■ xhtml.php


<?php
	class XHTML extends DOMDocument
	{
		private $doc;
		function __construct($version="1.0",$encoding="utf-8")
		{
			$this->doc=new parent($version,$encoding);
		}
		
		public function saveHTML()
		{
			return $this->doc->saveXML();
		}
		
		public function loadXHTML($contents,$option=0)
		{
			$this->setDomDocument($contents);
			/*
			$this->doc->loadHTML("<svg>a</svg>");
			$script=$this->doc->getElementsByTagName("script")->item(0)->nodeName;
			echo($script);
			$this->doc->loadXML($contents);
			*/
		}
		
		public function saveXHTML()
		{
			return $this->doc->saveXML();
		}
		
		private function setDomDocument($contents)
		{
			$doc=$this->doc;
			//$doc->preserveWhiteSpace=true;
			$doc->formatOutput=true;
			$target=$doc->createElement("root");
			//$target->setAttribute("xmlns","http://www.w3.org/1999/xhtml");
			$target=$doc->appendChild($target);
			$text="";
			$prev="";
			$type="text";
			$nodeName="";
			$attribute="";
			$quot_type="";
			$result="";
			foreach(str_split($contents) as $str)
			{
				switch($str)
				{
					case "<" :
							switch($type)
							{
								case "text" :
										$type="tagL";
										if(strlen($text)!=0)
										{
											$target->appendChild($doc->createTextNode($text));
											$text="";
										}
								break;

								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "cdataR" :
										$type="cdataC";
										$text.=$str;
								break;

								case "dtd" :

								break;

								default :
										$text.=$str;
							}
					break;

					case ">" :
							switch($type)
							{
								case "tagL" :
										$nodeName=strtolower(trim($text));
										switch($nodeName)
										{
												case "area" :
												case "base" :
												case "br" :
												case "col" :
												case "command" :
												case "embed" :
												case "hr" :
												case "img" :
												case "input" :
												case "keygen" :
												case "link" :
												case "meta" :
												case "param" :
												case "source" :
												case "track" :
												case "wbr" :
														$target=$target->appendChild($doc->createElement($nodeName));
														$target=$target->parentNode;
														$text="";
														$type="text";
												break;
												
												case "textarea" :
														$target=$target->appendChild($doc->createElement($nodeName));
														$text="";
														$type="textArea";
												break;
												
												default :
														$target=$target->appendChild($doc->createElement($nodeName));
														$text="";
														$type=($nodeName=="script")? "script" : "text";
										}
								break;

								case "tagR" :
										$target=$target->parentNode;
										$text="";
										$type="text";
								break;

								case "commentR" :
										$text=preg_replace("/^--|--$/si","",$text);
										$target->appendChild($doc->createComment($text));
										$text="";
										$type="text";
								break;

								case "cdataR" :
										$text=preg_replace("/^\[[a-zA-Z]+\[|]]$/si","",$text);
										$target->appendChild($doc->createCDATASection($text));
										$text="";
										$type="text";
								break;
								
								case "script" :
									if($quot_type==""&&preg_match("/[.]*<\/script$/si",$text))
									{
										$text=preg_replace("/^.*<!\[CDATA\[(.*)\]\]>.*<\/script$/si","$1",$text);
										$text=preg_replace("/<\/script$/si","",$text);
										if(strlen(trim($text))!=0)
										{
											$target->appendChild($doc->createCDATASection($text));
										}
										$target=$target->parentNode;
										$type="text";
										$text="";
									}
									else
									{
										$text.=$str;
									}
								break;

								case "textArea" :
									if($quot_type==""&&preg_match("/.*<\/textarea$/si",$text))
									{
										$text=preg_replace("/^textarea|<\/textarea$/si","",$text);
										if(strlen(trim($text))!=0)
										{
											$target->appendChild($doc->createCDATASection($text));
										}
										$target=$target->parentNode;
										$type="text";
										$text="";
									}
									else
									{
										$text.=$str;
									}
								break;
								
								case "attribute" :
								case "valueL" :
											$text=preg_replace("/[ 	\r\n]*=[ 	\r\n]*/s","=",trim($text));
											foreach(explode(" ",$text) as $val)
											{
												if(!empty($val))
												{
													$attr=explode("=",$val);
													if(count($attr)==2)
													{
														$target->setAttribute(trim($attr[0]),trim($attr[1]));
													}
													else
													{
														$target->setAttribute(trim($attr[0]),trim($attr[0]));
													}
													$attribute=trim($val[0]);
												}
											}
											switch($nodeName)
											{
												case "area" :
												case "base" :
												case "br" :
												case "col" :
												case "command" :
												case "embed" :
												case "hr" :
												case "img" :
												case "input" :
												case "keygen" :
												case "link" :
												case "meta" :
												case "param" :
												case "source" :
												case "track" :
												case "wbr" :
														$target=$target->parentNode;
														$type="text";
														$text="";
												break;
												
												case "textarea" :
														$type="textArea";
														$text="";
												break;
												
													default:
															$type=($nodeName=="script")? "script" : "text";
															$text="";
											}
								break;

								case "dtd" :
										$type="text";
										$text="";
								break;
								
								
								default :
										$text.=$str;
							}
					break;

					case "/" :
							switch($type)
							{
								case "tagL" :
										$nodeName=strtolower(trim($text));
										switch($nodeName)
										{
												case "area" :
												case "base" :
												case "br" :
												case "col" :
												case "command" :
												case "embed" :
												case "hr" :
												case "img" :
												case "input" :
												case "keygen" :
												case "link" :
												case "meta" :
												case "param" :
												case "source" :
												case "track" :
												case "wbr" :
														$target=$target->appendChild($doc->createElement($nodeName));
														$type="tagR";
												break;
												
												default:
														$type="tagR";
										}
								break;

								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "cdataR" :
										$type="cdataC";
										$text.=$str;
								break;

								case "attribute" :
										if(strlen(trim($text))!=0)
										{
											$attr=trim($text);
											foreach(explode(" ",$attr) as $val)
											{
												if(!empty($val))
												{
													$val=explode("=",$val);
													if(count($val)==1)
													{
														$target->setAttribute(trim($val[0]),trim($val[0]));
													}
													else
													{
														$target->setAttribute(trim($val[0]),trim($val[1]));
													}
												}
											}
										}
										$type="tagR";
								break;

								case "valueL" :
										//text.append(str);
								break;
								case "dtd" :

								break;

								default :
										$text.=$str;
							}
					break;

					case "!" :
							switch($type)
							{
								case "tagL" :
										if($prev=="<")
										{
											$type="dtd";
										}
								break;

								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "cdataR" :
										$type="cdataC";
										$text.=$str;
								break;

								case "attribute" :
								case "dtd" :

								break;

								default :
										$text.=$str;
							}
					break;

					case "?" :
							switch($type)
							{
								case "tagL" :
										if($prev=="<")
										{
											$type="dtd";
										}
								break;

								default :
										$text.=$str;
							}
					break;

					case "-" :
							switch($type)
							{
								case "dtd" :
										if($prev=="-")
										{
											$type="commentL";
										}
										$text.=$str;
								break;

								case "commentL" :
										if($prev=="-")
										{
											$type="commentR";
										}
										$text.=$str;
								break;

								case "cdataR" :
										$type="cdataC";
										$text.=$str;
								break;

								default :
										$text.=$str;
							}

					break;

					case "[" :
							switch($type)
							{
								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "dtd" :
										if($prev=="!")
										{
											$type="cdataC";
										}
										$text.=$str;
								break;

								case "cdataR" :
										$type="cdataC";
										$text.=$str;
								break;

								case "attribute":

								break;

								default:
										$text.=$str;
							}
					break;

					case "]" :
							switch($type)
							{
								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "cdataC" :
										if($prev=="]")
										{
											$type="cdataR";
										}
										$text.=$str;
								break;

								case "attribute" :
								case "dtd" :

								break;

								default:
										$text.=$str;
							}
					break;

					case " " :
					case "	" :
							switch($type)
							{
								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "cdataR" :
										$type="cdataC";
										$text.=$str;

								break;

								case "tagL" :
										$nodeName=strtolower(trim($text));
										$target=$target->appendChild($doc->createElement($nodeName));
										$text="";
										$type="attribute";
								break;

								case "dtd" :

								break;
								
								default:
										$text.=$str;
							}
					break;
					
					case "=" :
							switch($type)
							{
								case "attribute" :
										$type="valueL";
										$attribute=trim($text);
										$text.=$str;
								break;

								case "valueR" :
									if($quot_type=="")
									{
											$type="valueL";
											$attribute=trim($text);
									}
									else
									{
										$text.=$str;
									}
								break;
								
								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "dtd" :

								break;
								
								default:
										$text.=$str;
							}
					break;

					case "'" :
					case "\"" :
							switch($type)
							{
								case "valueL" :
										if($quot_type=="")
										{
											$quot_type=$str;
											$type="valueR";
											$text="";
										}
								break;

								case "valueR" :
										if($quot_type==$str)
										{
											$attrs=explode(" ",trim($attribute));
											for($i=0;$i<count($attrs);$i++)
											{
												if(!empty($attrs[$i]))
												{
													$result=(count($attrs)-1!=$i)? $attrs[$i] : $text;
													$equal=explode("=",$attrs[$i]);
													if(count($attrs)!=0&&count($equal)==1)
													{
														$target->setAttribute($attrs[$i],$result);
													}
													else
													{
														$target->setAttribute($equal[0],$equal[1]);
													}
												}
											}
											$type="attribute";
											$quot_type="";
											$text="";
										}
										else
										{
											$text.=$str;
										}
								break;

								case "script" :
										if($quot_type=="")
										{
											$quot_type=$str;
											$type="js_value";
										}
										$text.=$str;
								break;

								case "js_value" :
										if($prev!="\\")
										{
											$quot_type="";
											$type="script";
										}
										$text.=$str;
								break;
								
								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "dtd" :

								break;
								
								default:
										$text.=$str;
							}
					break;

					case "\r" :

					break;
					
					default :
							switch($type)
							{
								case "commentR" :
										$type="commentL";
										$text.=$str;
								break;

								case "cdataR" :
										$type="cdataC";
										$text.=$str;
								break;

								case "dtd" :

								break;

								default:
										$text.=$str;
							}
				}
				$prev=$str;
			}//end of foreach
			if(strlen($text)!=0)
			{
				$target->appendChild($doc->createTextNode($text));
			}
		}
	}

	if(isset($_POST["template"]))
	{
		libxml_use_internal_errors(true);
		$doc=new XHTML("1.0","utf-8");
		$contents=rawurldecode($_POST["template"]);
		$doc->loadXHTML($contents);
		//header("Content-type: text/xml");
		echo($doc->saveXHTML());
	}
?>

前回作成した java HTMLドキュメント文字列のツリー化(2)の訂正。
HTML ドキュメントを XML へ変換する java プログラムです。
XML, DTD宣言がある場合、その記述を無視します。
色々修正してます。
google, yahoo, bing 検索のトップページのソースを入力してテストしてみました。
javascript, textarea タグの内容 は CDATA へ、HTML ドキュメントを XML ツリー構造に変換して出力します。

■ XHTML_Test.java 実行結果

yahoo トップページのソースを入力してプログラムを実行してみました。

■ XHTML_Test.java


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

class XHTML_Test
{

	class XHTML
	{
		private Document document;
		public Element createDocumentElement(String root) throws Exception
		{
			DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
			document=documentBuilder.newDocument();
			Element rootElement=document.createElement(root);
			document.appendChild(rootElement);
			return rootElement;
		}
		public Document load(String fileName) throws Exception
		{
			DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
			FileInputStream fileInputStream=new FileInputStream(fileName);
			document=documentBuilder.parse(fileInputStream);
			fileInputStream.close();
			return document;
		}
		public void write(String fileName,String encoding) throws Exception
		{
			DOMImplementation domImplementation=document.getImplementation();
			DOMImplementationLS domImplementationLS=(DOMImplementationLS)domImplementation.getFeature("LS","3.0");
			LSOutput lsOutput=domImplementationLS.createLSOutput();
			lsOutput.setEncoding(encoding);//エンコード指定
			LSSerializer lsSerializer=domImplementationLS.createLSSerializer();
			OutputStream outputStream=new FileOutputStream(fileName);
			lsOutput.setByteStream(outputStream);
			lsSerializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
			lsSerializer.write(document,lsOutput);
			outputStream.close();
		}
		public void output() throws Exception
		{
			DOMImplementation domImplementation=document.getImplementation();
			DOMImplementationLS domImplementationLS=(DOMImplementationLS)domImplementation.getFeature("LS","3.0");
			LSSerializer lsSerializer=domImplementationLS.createLSSerializer();
			lsSerializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
			System.out.println(lsSerializer.writeToString((Node)document.getDocumentElement()));
		}
		public Document getDocument()
		{
			return document;
		}

		public void loadXHTML(String fileName,String encoding)  throws FileNotFoundException, IOException, Exception
		{
			try(BufferedReader input=new BufferedReader(new InputStreamReader(new FileInputStream(fileName),encoding)))
			{
				int ch;
				StringBuffer text=new StringBuffer();
				String prev="";
				String type="text";
				String nodeName="";
				String attribute="";
				String quot_type="";
				String result;
				Element target=createDocumentElement("root");
				//target.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
				while((ch=input.read())!=-1)
				{
					String str=String.valueOf((char)ch);
					switch(str)
					{
						case "<" :
								switch(type)
								{
									case "text" :
											type="tagL";
											if(text.length()!=0)
											{
												target.appendChild(document.createTextNode(text.toString()));
												text=new StringBuffer();
											}
									break;

									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "dtd" :

									break;

									default :
											text.append(str);
								}
						break;

						case ">" :
								switch(type)
								{
									case "tagL" :
											nodeName=text.toString().trim().toLowerCase();
											switch(nodeName)
											{
													case "area" :
													case "base" :
													case "br" :
													case "col" :
													case "command" :
													case "embed" :
													case "hr" :
													case "img" :
													case "input" :
													case "keygen" :
													case "link" :
													case "meta" :
													case "param" :
													case "source" :
													case "track" :
													case "wbr" :
															target=(Element)target.appendChild(document.createElement(nodeName));
															target=(Element)target.getParentNode();
															text=new StringBuffer();
															type="text";
													break;

													case "textarea" :
															target=(Element)target.appendChild(document.createElement(nodeName));
															text=new StringBuffer();
															type="textArea";
													break;
													
													default :
															target=(Element)target.appendChild(document.createElement(nodeName));
															text=new StringBuffer();
															type=(nodeName.equals("script"))? "script" : "text";
											}
									break;

									case "tagR" :
											target=(Element)target.getParentNode();
											text=new StringBuffer();
											type="text";
									break;

									case "commentR" :
											result=text.toString().replaceAll("(?i)^--|--$","");
											target.appendChild(document.createComment(result));
											text=new StringBuffer();
											type="text";
									break;

									case "cdataR" :
											result=text.toString().replaceAll("(?i)^\\[[a-zA-Z]+\\[|]]$","");
											target.appendChild(document.createCDATASection(result));
											text=new StringBuffer();
											type="text";
									break;

									case "script" :
									
											Pattern p1=Pattern.compile("(?i)[.]*<\\/script$");
											Matcher m1=p1.matcher(text.toString());
											if(quot_type.equals("")&&m1.find())
											{
												result=text.toString().replaceAll("(?is)^.*<!\\[CDATA\\[(.*)\\]\\]>.*<\\/script$","$1");
												result=result.replaceAll("(?i)<\\/script$","");
												if(result.length()!=0)
												{
													target.appendChild(document.createCDATASection(result));
												}
												target=(Element)target.getParentNode();
												type="text";
												text=new StringBuffer();
											}
											else
											{
												text.append(str);
											}
									break;

									case "textArea" :
											Pattern p2=Pattern.compile("(?i)[.]*<\\/textarea$");
											Matcher m2=p2.matcher(text.toString());
											if(quot_type.equals("")&&m2.find())
											{
												result=text.toString().replaceAll("(?i)<\\/textarea$","");
												if(result.length()!=0)
												{
													target.appendChild(document.createCDATASection(result));
												}
												target=(Element)target.getParentNode();
												type="text";
												text=new StringBuffer();
											}
											else
											{
												text.append(str);
											}
									break;

									case "valueL" :
									case "attribute" :
												String value=text.toString().trim().replaceAll("[ 	\r\n]*=[ 	\r\n]*","=");
												if(text.toString().trim().length()!=0)
												{
													String attr=text.toString().trim();
													for(String obj : attr.toString().split(" "))
													{
														String[] equal=obj.split("=");
														if(!obj.equals("")&&equal.length==1)
														{
															target.setAttribute(obj,obj);
														}
														else
														{
															target.setAttribute(equal[0],equal[1]);
														}
													}
												}
												switch(nodeName)
												{
													case "area" :
													case "base" :
													case "br" :
													case "col" :
													case "command" :
													case "embed" :
													case "hr" :
													case "img" :
													case "input" :
													case "keygen" :
													case "link" :
													case "meta" :
													case "param" :
													case "source" :
													case "track" :
													case "wbr" :
															target=(Element)target.getParentNode();
															type="text";
															text=new StringBuffer();
													break;

													case "textarea" :
															type="textArea";
															text=new StringBuffer();
													break;
													
														default:
																type=(nodeName.equals("script"))? "script" : "text";
																text=new StringBuffer();
												}
									break;

									case "dtd" :
											type="text";
											text=new StringBuffer();
									break;
									
									
									default :
											text.append(str);
								}
								
						break;

						case "/" :
								switch(type)
								{
									case "tagL" :
											nodeName=text.toString().trim().toLowerCase();
											switch(nodeName)
											{
													case "area" :
													case "base" :
													case "br" :
													case "col" :
													case "command" :
													case "embed" :
													case "hr" :
													case "img" :
													case "input" :
													case "keygen" :
													case "link" :
													case "meta" :
													case "param" :
													case "source" :
													case "track" :
													case "wbr" :
															target=(Element)target.appendChild(document.createElement(nodeName));
															type="tagR";
													break;
													
													default:
															type="tagR";
											}
									break;

									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "attribute" :
											if(text.toString().trim().length()!=0)
											{
												String attr=text.toString().trim();
												for(String obj : attr.split(" "))
												{
													String[] equal=obj.split("=");
													if(!obj.equals("")&&equal.length==1)
													{
														target.setAttribute(obj,obj);
													}
													else
													{
														target.setAttribute(equal[0],equal[1]);
													}
												}
											}
											type="tagR";
									break;

									case "valueL" :
											//text.append(str);
									break;
									case "dtd" :

									break;

									default :
											text.append(str);
								}
						break;

						case "!" :
								switch(type)
								{
									case "tagL" :
											if(prev.equals("<"))
											{
												type="dtd";
											}
									break;

									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "attribute" :
									case "dtd" :

									break;

									default :
											text.append(str);
								}

						break;

						case "?" :
								switch(type)
								{
									case "tagL" :
											if(prev.equals("<"))
											{
												type="dtd";
											}
									break;

									default :
											text.append(str);
								}
						break;

						case "-" :
								switch(type)
								{
									case "dtd" :
											if(prev.equals("-"))
											{
												type="commentL";
											}
											text.append(str);
									break;

									case "commentL" :
											if("-".equals(prev))
											{
												type="commentR";
											}
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									default :
											text.append(str);
								}

						break;

						case "[" :
								switch(type)
								{
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "dtd" :
											if(prev.equals("!"))
											{
												type="cdataC";
											}
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "attribute":

									break;

									default:
											text.append(str);
								}
						break;

						case "]" :
								switch(type)
								{
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataC" :
											if(prev.equals("]"))
											{
												type="cdataR";
											}
											text.append(str);
									break;

									case "attribute" :
									case "dtd" :

									break;

									default:
											text.append(str);
								}
						break;

						case " " :
						case "	" :
								switch(type)
								{
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);

									break;

									case "tagL" :
											nodeName=text.toString().trim().toLowerCase();
											target=(Element)target.appendChild(document.createElement(nodeName));
											text=new StringBuffer();
											type="attribute";
									break;

									case "dtd" :

									break;
									
									default:
											text.append(str);
								}
						break;
						
						case "=" :
								switch(type)
								{
									case "attribute" :
											type="valueL";
											attribute=text.toString().trim();
											text.append(str);
									break;

									case "valueR" :
										if(quot_type.equals(""))
										{
												type="valueL";
												attribute=text.toString().trim();
										}
										else
										{
											text.append(str);
										}
									break;
									
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "dtd" :

									break;
									
									default:
											text.append(str);
								}
						break;

						case "'" :
						case "\"" :
								switch(type)
								{
									case "valueL" :
											if(quot_type.equals(""))
											{
												quot_type=str;
												type="valueR";
												text=new StringBuffer();
											}
									break;

									case "valueR" :
											if(quot_type.equals(str))
											{
												String[] attrs=attribute.toString().trim().split(" ");
												for(int i=0;i<attrs.length;i++)
												{
													result=(attrs.length-1!=i)? attrs[i] : text.toString();
													String[] equal=attrs[i].split("=");
													if(attrs[i].length()!=0&&equal.length==1)
													{
														target.setAttribute(attrs[i],result);
													}
													else
													{
														target.setAttribute(equal[0],equal[1]);
													}
												}
												type="attribute";
												quot_type="";
												text=new StringBuffer();
											}
											else
											{
												text.append(str);
											}
									break;

									case "script" :
											if(quot_type.equals(""))
											{
												quot_type=str;
												type="js_value";
											}
											text.append(str);
									break;

									case "js_value" :
											if(!prev.equals("\\"))
											{
												quot_type="";
												type="script";
											}
											text.append(str);
									break;
									
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "dtd" :

									break;
									
									default:
											text.append(str);
								}
						break;

						case "\r" :

						break;
						
						default :
								switch(type)
								{
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "dtd" :

									break;

									default:
											text.append(str);
								}
					}
					prev=str;
				}
				if(text.length()!=0)
				{
					target.appendChild(document.createTextNode(text.toString()));
				}
				input.close();
			}
		}
	}

	XHTML_Test() throws Exception
	{
		XHTML xmlObj=new XHTML();
		xmlObj.loadXHTML("template.xml","utf-8");
		xmlObj.write("result.xml","utf-8");
	}

	public static void main(String args[]) throws Exception
	{
		new XHTML_Test();
	}
}

訂正 → java HTMLドキュメント文字列のツリー化(3)[ XML出力 ]

前回作成した java HTMLドキュメント文字列のツリー化(1)の訂正。
まだ、文書型 DTD の宣言には対応出来ていません。

参考にさせていただいたサイト ( html5 の空要素 ) → 空要素

html ドキュメント ( 文字列 )を一文字づつ読み込んで、 XML ツリーを生成するテスト。
DTD 宣言のない HTML5 文章を XML のツリー構造へ変換する java プログラムです。
前回のテストから訂正箇所は、
1) html5 で定義されている空要素の閉じる記号 ( "/" ) がなくてもツリー化出来るようにした。
2) 属性と属性値を区切る ( "=" ) の前後に半角スペース, タブが存在する場合のエラー処理。
3) 属性、又は属性値が単独で存在する場合の処理。
4) 属性値がシングルクォーテーション, 又はダブルクォーテーションで囲ってない場合の処理。
テストした範囲での動作確認です。

  • html5 の空要素、<br> などは <br /> のように "/" をつけても付けなくても同じ結果が出力されますん?。( img,input,link など )
  • *コメントの記述に対応?。開始タグ( <! ) 終了タグ( --> )
  • *CDATA の記述に対応?。開始タグ( <![ ) 終了タグ( ]]> )
  • *javascript タグの内容は CDATA として出力。

■ 読み込む html5? ドキュメント template.xml。

読み込む html5? ドキュメント

今回テストした HTML ドキュメントは HTML5 に準じた文章ではありません。
空タグに対して閉じる記号の "/" を記述したり、 ダブルクォーテーションを省いたりしてテストしてます。

■ java プログラム実行後、出力された XML ドキュメント result.xml

java プログラム実行後、出力された XML

今回作成した html5 ドキュメントを XML 化するプログラムに google 検索のトップ画面のソースを入力してテスト。
とりあえず、ツリー化は出来てるようだけど、正しくツリー化されてるかはわかりません。\(^o^)/

■ google トップ画面のソースを XML ツリー化 ( google chrome ブラウザ表示 )

chrome ブラウザ xml 表示

■ XHTML_Test.java


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

class XHTML_Test
{

	class XHTML
	{
		private Document document;
		public Element createDocumentElement(String root) throws Exception
		{
			DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
			document=documentBuilder.newDocument();
			Element rootElement=document.createElement(root);
			document.appendChild(rootElement);
			return rootElement;
		}
		public Document load(String fileName) throws Exception
		{
			DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
			FileInputStream fileInputStream=new FileInputStream(fileName);
			document=documentBuilder.parse(fileInputStream);
			fileInputStream.close();
			return document;
		}
		public void write(String fileName,String encoding) throws Exception
		{
			DOMImplementation domImplementation=document.getImplementation();
			DOMImplementationLS domImplementationLS=(DOMImplementationLS)domImplementation.getFeature("LS","3.0");
			LSOutput lsOutput=domImplementationLS.createLSOutput();
			lsOutput.setEncoding(encoding);//エンコード指定
			LSSerializer lsSerializer=domImplementationLS.createLSSerializer();
			OutputStream outputStream=new FileOutputStream(fileName);
			lsOutput.setByteStream(outputStream);
			lsSerializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
			lsSerializer.write(document,lsOutput);
			outputStream.close();
		}
		public void output() throws Exception
		{
			DOMImplementation domImplementation=document.getImplementation();
			DOMImplementationLS domImplementationLS=(DOMImplementationLS)domImplementation.getFeature("LS","3.0");
			LSSerializer lsSerializer=domImplementationLS.createLSSerializer();
			lsSerializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
			System.out.println(lsSerializer.writeToString((Node)document.getDocumentElement()));
		}
		public Document getDocument()
		{
			return document;
		}

		public void loadXHTML(String fileName,String encoding)  throws FileNotFoundException, IOException, Exception
		{
			try(BufferedReader input=new BufferedReader(new InputStreamReader(new FileInputStream(fileName),encoding)))
			{
				int ch;
				StringBuffer text=new StringBuffer();
				String prev="";
				String type="text";
				String nodeName="";
				String attribute="";
				String quot_type="";
				String result;
				Element target=createDocumentElement("div");
				//target.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
				while((ch=input.read())!=-1)
				{
					String str=String.valueOf((char)ch);
					switch(str)
					{
						case "<" :
								switch(type)
								{
									case "text" :
											type="tagL";
											if(text.length()!=0)
											{
												target.appendChild(document.createTextNode(text.toString()));
												text=new StringBuffer();
											}
									break;

									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									default :
											text.append(str);
								}
						break;

						case ">" :
								
								switch(type)
								{
									case "tagL" :
											nodeName=text.toString().trim().toLowerCase();
											switch(nodeName)
											{
													case "area" :
													case "base" :
													case "br" :
													case "col" :
													case "command" :
													case "embed" :
													case "hr" :
													case "img" :
													case "input" :
													case "keygen" :
													case "link" :
													case "meta" :
													case "param" :
													case "source" :
													case "track" :
													case "wbr" :
															target=(Element)target.appendChild(document.createElement(nodeName));
															target=(Element)target.getParentNode();
															text=new StringBuffer();
															type="text";
													break;
													
													default :
															target=(Element)target.appendChild(document.createElement(nodeName));
															text=new StringBuffer();
															type=(nodeName.equals("script"))? "script" : "text";
											}
									break;

									case "tagR" :
											target=(Element)target.getParentNode();
											text=new StringBuffer();
											type="text";
									break;

									case "commentR" :
											result=text.toString().replaceAll("(?i)^--|--$","");
											target.appendChild(document.createComment(result));
											text=new StringBuffer();
											type="text";
									break;

									case "cdataR" :
											result=text.toString().replaceAll("(?i)^\\[[a-zA-Z]+\\[|]]$","");
											target.appendChild(document.createCDATASection(result));
											text=new StringBuffer();
											type="text";
									break;

									case "attribute" :
											switch(nodeName)
											{
													case "area" :
													case "base" :
													case "br" :
													case "col" :
													case "command" :
													case "embed" :
													case "hr" :
													case "img" :
													case "input" :
													case "keygen" :
													case "link" :
													case "meta" :
													case "param" :
													case "source" :
													case "track" :
													case "wbr" :
															if(text.toString().trim().length()!=0)
															{
																String attr=text.toString().trim();
																for(String obj : attr.toString().split(" "))
																{
																	String[] equal=obj.split("=");
																	if(!obj.equals("")&&equal.length==1)
																	{
																		target.setAttribute(obj,obj);
																	}
																	else
																	{
																		target.setAttribute(equal[0],equal[1]);
																	}
																}
															}
															target=(Element)target.getParentNode();
															text=new StringBuffer();
															type="text";
													break;
													
													default :
															if(text.toString().trim().length()!=0)
															{
																String attr=text.toString().trim();
																for(String obj : attr.toString().split(" "))
																{
																	String[] equal=obj.split("=");
																	if(!obj.equals("")&&equal.length==1)
																	{
																		target.setAttribute(obj,obj);
																	}
																	else
																	{
																		target.setAttribute(equal[0],equal[1]);
																	}
																}
															}
															text=new StringBuffer();
															type=(nodeName.equals("script"))? "script" : "text";
											}
									break;

									case "script" :
											Pattern p=Pattern.compile("(?i)[.]*<\\/script$");
											Matcher m=p.matcher(text.toString());
											if(quot_type.equals("")&&m.find())
											{
												result=text.toString().replaceAll("(?i)<\\/script$","");
												target.appendChild(document.createCDATASection(result));
												target=(Element)target.getParentNode();
												type="text";
												text=new StringBuffer();
											}
											else
											{
												text.append(str);
											}
									break;

									case "valueL" :
												String value=text.toString().trim().replaceAll("[ 	\r\n]*=[ 	\r\n]*","=");
												for(String obj : value.split(" "))
												{
													String[] attr=obj.split("=");
													try
													{
														target.setAttribute(attr[0].trim(),attr[1].trim());
													}catch(ArrayIndexOutOfBoundsException e)
													{
														target.setAttribute(attr[0].trim(),attr[0].trim());
													}
													attribute=attr[0].trim();
												}
												switch(nodeName)
												{
													case "area" :
													case "base" :
													case "br" :
													case "col" :
													case "command" :
													case "embed" :
													case "hr" :
													case "img" :
													case "input" :
													case "keygen" :
													case "link" :
													case "meta" :
													case "param" :
													case "source" :
													case "track" :
													case "wbr" :
															target=(Element)target.getParentNode();
															type="text";
															text=new StringBuffer();
													break;
														default:
																type="text";
																text=new StringBuffer();
												}
									break;
									
									default :
											text.append(str);
								}
						break;

						case "/" :
								switch(type)
								{
									case "tagL" :
											nodeName=text.toString().trim().toLowerCase();
											switch(nodeName)
											{
													case "area" :
													case "base" :
													case "br" :
													case "col" :
													case "command" :
													case "embed" :
													case "hr" :
													case "img" :
													case "input" :
													case "keygen" :
													case "link" :
													case "meta" :
													case "param" :
													case "source" :
													case "track" :
													case "wbr" :
															target=(Element)target.appendChild(document.createElement(nodeName));
															type="tagR";
													break;
													
													default:
															type="tagR";
											}
									break;

									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "attribute" :
											if(text.toString().trim().length()!=0)
											{
												String attr=text.toString().trim();
												for(String obj : attr.split(" "))
												{
													String[] equal=obj.split("=");
													if(!obj.equals("")&&equal.length==1)
													{
														target.setAttribute(obj,obj);
													}
													else
													{
														target.setAttribute(equal[0],equal[1]);
													}
												}
											}
											type="tagR";
									break;

									case "valueL" :
											//text.append(str);
									
									break;

									default :
											text.append(str);
								}
						break;

						case "!" :
								switch(type)
								{
									case "tagL" :
											type="commentL";
									break;

									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "attribute" :

									break;

									default :
											text.append(str);
								}

						break;

						case "-" :
								switch(type)
								{
									case "commentL" :
											if(prev.equals("-"))
											{
												type="commentR";
											}
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									default :
											text.append(str);
								}

						break;

						case "[" :
								switch(type)
								{
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "commentL" :
											if(prev.equals("!"))
											{
												type="cdataC";
											}
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);
									break;

									case "attribute":

									break;

									default:
											text.append(str);
								}
						break;

						case "]" :
								switch(type)
								{
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataC" :
											if(prev.equals("]"))
											{
												type="cdataR";
											}
											text.append(str);
									break;

									case "attribute" :

									break;

									default:
											text.append(str);
								}
						break;

						case " " :
						case "	" :
								switch(type)
								{
									case "commentR" :
											type="commentL";
											text.append(str);
									break;

									case "cdataR" :
											type="cdataC";
											text.append(str);

									break;

									case "tagL" :
											nodeName=text.toString().trim().toLowerCase();
											target=(Element)target.appendChild(document.createElement(nodeName));
											text=new StringBuffer();
											type="attribute";
									break;
									
									default:
											text.append(str);
								}
						break;
						
						case "=" :
								switch(type)
								{
									case "attribute" :
											type="valueL";
											attribute=text.toString().trim();
											text.append(str);
									break;

									case "valueR" :
										if(quot_type.equals(""))
										{
												type="valueL";
												attribute=text.toString().trim();
										}
										else
										{
											text.append(str);
										}
									break;

									default:
											text.append(str);
								}
						break;

						case "'" :
						case "\"" :
								switch(type)
								{
									case "valueL" :
											if(quot_type.equals(""))
											{
												String value=text.toString().trim().replaceAll("[ 	\r\n]*=[ 	\r\n]*","=");
												for(String obj : value.split(" "))
												{
													String[] attr=obj.split("=");
													try
													{
														target.setAttribute(attr[0].trim(),attr[1].trim());
													}catch(ArrayIndexOutOfBoundsException e)
													{
														target.setAttribute(attr[0].trim(),attr[0].trim());
													}
													attribute=attr[0].trim();
												}
												quot_type=str;
												type="valueR";
												text=new StringBuffer();
											}
									break;

									case "valueR" :
											if(quot_type.equals(str))
											{
												String[] attrs=attribute.toString().trim().split(" ");
												for(int i=0;i<attrs.length;i++)
												{
													result=(attrs.length-1!=i)? attrs[i] : text.toString();
													String[] equal=attrs[i].split("=");
													if(attrs[i].length()!=0&&equal.length==1)
													{
														target.setAttribute(attrs[i],result);
													}
													else
													{
														target.setAttribute(equal[0],equal[1]);
													}
												}
												type="attribute";
												quot_type="";
												text=new StringBuffer();
											}
											else
											{
												text.append(str);
											}
									break;

									case "script" :
											if(quot_type.equals(""))
											{
												quot_type=str;
												type="js_value";
											}
											text.append(str);
									break;

									case "js_value" :
											if(!prev.equals("\\"))
											{
												quot_type="";
												type="script";
											}
											text.append(str);
									break;

									default:
											text.append(str);
								}
						break;

						case "\r" :

						break;
						
						default :
								switch(type)
								{
									case "commentR" :
											type="commentL";
									break;

									case "cdataR" :
											type="cdataC";
									break;
								}

								text.append(str);
					}
					prev=str;
				}
				if(text.length()!=0)
				{
					target.appendChild(document.createTextNode(text.toString()));
				}
				input.close();
			}
		}
	}

	XHTML_Test() throws Exception
	{
		XHTML xmlObj=new XHTML();
		xmlObj.loadXHTML("template.xml","utf-8");
		xmlObj.write("result.xml","utf-8");
	}

	public static void main(String args[]) throws Exception
	{
		new XHTML_Test();
	}
}

# スポンサードリンク