⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cast.java

📁 根据提供的XML Schema文件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/*
 * Classname Cast
 *
 * Version information 1.0
 *
 * Date 2008.1.18
 *
 * Author 熊小均
 *
 * Description 根据提供的XML Schema文件,生成相应的sql文件。sql文件中的内容主体为建表语句,根据sql文件在RDBMS中产生的表能够存储符合给定的XML Schema文件定义的合式的xml文档中的数据。
 */

public class Cast {
	private String schemafile;// 待解析的xml模式文件的文件名
	private String sql = "";// 生成的sql语句
	private Element root;// schema文件的根元素
	private HashMap<String, String> simpleType = new HashMap<String, String>();// 用于保存简单类型的类型名与类型实际的数据类型的映射关系的hash表。key为名称,值为类型
	private HashMap<String, String> complexType = new HashMap<String, String>();// 用于保存元素名与其的数据类型的映射关系的hash表。key为名称,值为类型。
	private HashMap<String, HashMap<String, String>> tableType = new HashMap<String, HashMap<String, String>>();// 用于保存元素数据类型与保存其属性内容的映射关系的hash表,键为类型名,值为属性表。
	private HashMap<String, ArrayList<String>> key = new HashMap<String, ArrayList<String>>();// 保存主键信息的hash表,键为表名,值为主键名组成的字符串链表
	private HashMap<String, ArrayList<String[]>> restriction = new HashMap<String, ArrayList<String[]>>();// 用于保存各种简单类型的约束条件的数据结构,键为表名,值为一个链表,链表的每一项为一个字符串数组,数组第一项为属性名,第二项为最小值,第三项为最大值,第四项为可选值,第五项为字符串的匹配模式
	private HashMap<String, String> keyrefToTableName = new HashMap<String, String>();// 保存外键映射信息的hash表,键为外键名,值为表名

	public Cast(String filename) throws Exception {
		schemafile = filename;
		root = getRoot(schemafile);// 获取dom树的根元素
		castToTable();// 生成各种数据结构,填充用于保存结构信息的几张表
	}

	public String getSchemafile() {
		return schemafile;
	}

	private Element getRoot(String filename) throws Exception {// 取得xml文件的dom树的根元素
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		Document doc = factory.newDocumentBuilder().parse(filename);
		Element rootElement = doc.getDocumentElement();
		if (rootElement == null) {// 如果根元素为空,向上抛出异常
			throw new Exception();
		}
		return rootElement;
	}

	private void castToTable() throws Exception {

		NodeList simple = castSimpleToTable();

		// 处理复杂类型
		NodeList complex = root.getElementsByTagName("complexType");
		Element current;

		NodeList element = null;// 子元素节点列表
		Element currentelement = null;
		String elementtype = null;// 当前子元素的数据类型

		NodeList attri = null;// 属性节点列表
		Element currentattri = null;

		NodeList keynode = null;// 主键说明节点列表
		NodeList currentkeynode = null;

		NodeList keyref = null;// 外键说明节点列表
		NodeList currentkeyref = null;

		HashMap<String, String> attrimap = null;
		for (int i = 0; i < complex.getLength(); i++) {
			current = (Element) complex.item(i);// 取当前的complexType节点
			element = current.getElementsByTagName("element");// 取当前complexType节点的子元素节点
			attri = current.getElementsByTagName("attribute");// 取当前complexType节点的属性节点
			keyref = current.getElementsByTagName("keyref");// 取当前complex节点的外键关系节点
			keynode = current.getElementsByTagName("key");// 取当前complex节点的主键节点
			attrimap = new HashMap<String, String>();// 该HashMap存储该complexType类型中的属性名与类型的映射关系
			ArrayList<String[]> attrirest = new ArrayList<String[]>();
			for (int j = 0; j < attri.getLength(); j++) {
				currentattri = (Element) attri.item(j);
				String attriname = currentattri.getAttribute("name");
				String attritype = currentattri.getAttribute("type");
				attrimap.put(attriname, simpleType.get(attritype));
				if (attritype.equalsIgnoreCase("string")// 如果是基本数据类型不用处理其约束条件
						|| attritype.equalsIgnoreCase("date")
						|| attritype.equalsIgnoreCase("integer")
						|| attritype.equalsIgnoreCase("float"))
					continue;
				String[] rest = castRestrictionToTable(simple, attriname,
						attritype);

				// 这步完成后,所有属性的数据类型均映射为基本数据类型并保存在HashMap中
				if (rest[0] != null)// 如果没有往rest数组中添加内容,则不能添加
					attrirest.add(rest);
			}

			for (int j = 0; j < element.getLength(); j++) {
				currentelement = (Element) element.item(j);
				elementtype = currentelement.getAttribute("type");
				if (simpleType.containsKey(elementtype)) {// 如果子元素的类型属于简单类型,将该子元素映射为属性
					String attriname = currentelement.getAttribute("name");
					String attritype = currentelement.getAttribute("type");
					String[] rest = castRestrictionToTable(simple, attriname,
							attritype);
					attrimap.put(attriname, simpleType.get(attritype));
					if (rest[0] != null)
						attrirest.add(rest);
				} else {// 否则在保存元素名的hash表中保存该元素的名称与类型
					complexType.put(currentelement.getAttribute("name"),
							elementtype);
				}
			}

			// 处理该节点的主键
			ArrayList<String> keyname = new ArrayList<String>();
			for (int j = 0; j < keynode.getLength(); j++) {
				currentkeynode = ((Element) keynode.item(j))
						.getElementsByTagName("field");
				for (int k = 0; k < currentkeynode.getLength(); k++) {
					String xpath = ((Element) currentkeynode.item(k))
							.getAttribute("xpath");
					if (xpath.startsWith("@"))
						xpath = xpath.substring(1);
					else if (xpath.startsWith("text(") && xpath.endsWith(")"))
						xpath = xpath.substring(5, xpath.length());
					keyname.add(xpath);
				}
			}
			if (keyname.size() != 0)
				key.put(current.getAttribute("name"), keyname);// 添加该表的主键信息

			// 处理该节点的外键关系
			for (int j = 0; j < keyref.getLength(); j++) {
				currentkeyref = ((Element) keyref.item(j))
						.getElementsByTagName("field");
				HashMap<String, String> keyrefattri = new HashMap<String, String>();
				ArrayList<String[]> refrest = new ArrayList<String[]>();
				for (int k = 0; k < currentkeyref.getLength(); k++) {
					String xpath = ((Element) currentkeyref.item(k))
							.getAttribute("xpath");
					if (xpath.startsWith("@"))
						xpath = xpath.substring(1);
					else if (xpath.startsWith("text(") && xpath.endsWith(")"))
						xpath = xpath.substring(5, xpath.length() - 1);
					if (!attrimap.containsKey(xpath))
						throw new Exception();
					keyrefattri.put(xpath, simpleType.get(attrimap.get(xpath)));// 将保存属性的hash表中的相关映射转移到另一张表中,用于表示外键引用
					keyrefToTableName.put(xpath, ((Element) keyref.item(j))
							.getAttribute("name"));
					for (int l = 0; l < attrirest.size(); l++)
						if (attrirest.get(l)[0].equals(xpath)) {// 将约束条件中的相关内容移动到新的表名下
							refrest.add(attrirest.get(l));
							attrirest.remove(l);
							break;
						}
					attrimap.remove(xpath);
				}
				keyrefattri.put("ID", "integer");// 添加id项
				keyrefattri.put("ParentID", "integer");// 添加父母节点的id项
				String keyrefname = ((Element) keyref.item(j))
						.getAttribute("name");
				tableType.put(keyrefname, keyrefattri);// 在生成的最终表中添加这张表示外键引用关系的表
				if (refrest.size() != 0) {
					restriction.put(keyrefname, refrest);
				}
				// 为保障该表最终能用来生成SQL语句,需要在complexType中添加相关信息
				complexType.put(keyrefname, keyrefname);
			}

			attrimap.put("ID", "integer");// 添加id属性
			attrimap.put("ParentID", "integer");// 添加父母节点的id属性
			attrimap.put("sequence", "integer");// 添加顺序属性
			if (attrimap.size() > 3)// 如果只有上述添加的三个属性则为空表,不添加
				tableType.put(current.getAttribute("name"), attrimap);// 添加该复杂数据类型生成的表
			restriction.put(current.getAttribute("name"), attrirest);
		}
		// 到此,所有可用来生成的表的休息都放入tableType中

		castElementToTable();
	}

	private String[] castRestrictionToTable(NodeList simple, String attriname,
			String attritype) {// 检查attritype的约束,将所有的约束条件保存在字符串数组中返回
		String[] rest = new String[5];
		for (int k = 0; k < simple.getLength(); k++) {
			Element currentsimple = (Element) simple.item(k);
			if (!currentsimple.getAttribute("name").equalsIgnoreCase(attritype))// 要找到该属性的约束条件
				continue;
			// 以下为约束条件的记录过程
			rest[0] = attriname;

			NodeList min = currentsimple.getElementsByTagName("minInclusive");// 最小值
			if (min.getLength() == 0)
				rest[1] = "-1";
			else
				rest[1] = min.item(0).getAttributes().getNamedItem("value")
						.getNodeValue();

			NodeList max = currentsimple.getElementsByTagName("maxInclusive");// 最大值
			if (max.getLength() == 0)
				rest[2] = "-1";
			else
				rest[2] = max.item(0).getAttributes().getNamedItem("value")
						.getNodeValue();

			NodeList enu = currentsimple.getElementsByTagName("enumeration");// 可选的值
			if (enu.getLength() == 0)
				rest[3] = "-1";
			else {
				String choice = "(";
				for (int l = 0; l < enu.getLength(); l++)
					choice += "'"
							+ enu.item(l).getAttributes().getNamedItem("value")
									.getNodeValue() + "',";
				rest[3] = choice.substring(0, choice.length() - 1) + ")";
			}
			rest[4] = "-1";//考虑到不同的数据库对字符串匹配约束格式的要求不太一致,去掉该约束
			/*NodeList pat = currentsimple.getElementsByTagName("pattern");// 字符串需要符合的模式
			if (pat.getLength() == 0)
				rest[4] = "-1";
			else
				rest[4] = pat.item(0).getAttributes().getNamedItem("value")
						.getNodeValue();*/
			break;
		}
		return rest;
	}

	private void castElementToTable() {
		// 处理元素类型,特别是根元素
		NodeList rootelement = root.getChildNodes();
		Node currentrootelement = null;
		for (int j = 0; j < rootelement.getLength(); j++) {
			currentrootelement = rootelement.item(j);
			if (currentrootelement.getNodeName().equals("element"))
				complexType.put("#"// 标记一下根元素
						+ currentrootelement.getAttributes().getNamedItem(
								"name").getNodeValue(), currentrootelement
						.getAttributes().getNamedItem("type").getNodeValue());
		}
	}

	private NodeList castSimpleToTable() {
		// 取得简单类型的名称与数据类型的映射
		NodeList simple = root.getElementsByTagName("simpleType");// 取得简单数据类型的链表
		Element current = null;
		Element currenttype = null;
		for (int i = 0; i < simple.getLength(); i++) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -