使用万能表单解析程序将表单数据封装成List<Map>
在JadePool中,提供了一个万能表单解析类ProcessForm,目的是提供对ProcessVO实现插入或更新记录的支持。它能将任意复杂的表单记录,包括所有的字段,包括单记录和多记录,解析并封装成List<Map>变量,这些结果可以作为ProcessVO插入、更新等方法的参数保存到数据库中。保存记录时,ProcessVO会自动过滤掉无效字段,只有表单中的字段名与数据库表中的字段名相同的数据才会保存到数据库中。目前,ProcessForm可能是世界上最完整的表单解析工具。
ProcessForm支持所有格式的文件上传,但不支持大文件的上传,能满足大多数网络环境的应用。
对于文件类型的字段,除了会解析出文件的内容外,还会给出文件的相关属性,这些属性按照下面的格式命名:
文件字段名_originfilename对于异步方式提交的表单数据,必须是Ajax标准格式,即xml格式。
/** * 解析用xml格式保存的记录,如使用Ajax上传的xml代码 在xml代码中出现多条记录时,第一个元素作为新的一条记录的参考标志 */ private List getListFromXml(String xmlFragment) throws ServletException { indexXmlList = -1; xmlRecordList = new ArrayList(); itemNameSet = new HashSet(); Document doc = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); doc = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlFragment))); } catch (Exception e) { e.printStackTrace(); } List list = visitNode(doc); return list; } /** * 解析用xml格式保存的记录,如使用Ajax上传的xml代码 * 该记录的值经由escape(form.XXX.value)方法转换成JavaScript中的Unicode编码格式 * 在xml代码中出现多条记录时,第一个元素作为新的一条记录的参考标志 */ private List getListFromXml(String xmlFragment, boolean isEcmaUnicode) throws ServletException, UnsupportedEncodingException { indexXmlList = -1; xmlRecordList = new ArrayList(); itemNameSet = new HashSet(); Document doc = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); doc = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlFragment))); } catch (Exception e) { e.printStackTrace(); } List list = visitNode(doc, isEcmaUnicode); return list; } private List visitNode(Node node) throws ServletException { if (node.getNodeType() == 1) { Node text = node.getFirstChild(); if (text != null) { if ("#text".equals(text.getNodeName())) { if (indexXmlList == -1) { firstXmlTagName = node.getNodeName(); itemNameSet.add(firstXmlTagName); indexXmlList++; } if (firstXmlTagName.equals(node.getNodeName())) { xmlRecord = new HashMap(); firstXmlTagParentNode = node.getParentNode(); xmlRecordList.add(xmlRecord); indexXmlList++; } //如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element肯定是字段 if ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) { itemNameSet.add(node.getNodeName()); ((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), text.getNodeValue()); } } } else { //叶子结点肯定是字段,但这是一个空值字段 if (indexXmlList == -1) { //throw new ServletException("The first element '<" + node.getNodeName() + ">' could not be null!");//禁止第一个字段为空值 } if (indexXmlList == -1) { //允许第一个字段为空值 firstXmlTagName = node.getNodeName(); itemNameSet.add(firstXmlTagName); indexXmlList++; } if (firstXmlTagName.equals(node.getNodeName())) { xmlRecord = new HashMap(); firstXmlTagParentNode = node.getParentNode(); xmlRecordList.add(xmlRecord); indexXmlList++; } //如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element的值为null if ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) { itemNameSet.add(node.getNodeName()); ((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), "");//用""替代null,还原表单的本义,如果元素存在,request.getParameter('元素名')则肯定会得到字符串,其长度大于等于0;如果元素不存在,request.getParameter('元素名')则肯定得到null } } } NodeList nodeList = node.getChildNodes(); if (nodeList != null && nodeList.getLength() > 0) { for (int i = 0; i < nodeList.getLength(); i++) { Node childNode = nodeList.item(i); visitNode(childNode); } } return xmlRecordList; } /** * 解析ajax方式上传的xml格式的记录集。 为xml应用修改 * 在ajax应用中如json,pvo中的Map对象,Array中元素,它们的值均不能含有回车符和换行符,因此 \r 将转换成"" \n 将转换成"" * 此方法可以作为默认的xml解析方法,不论用户上传的数据是否作了escape转换,都能得到希望的结果 */ private List visitNode(Node node, boolean isEcmaUnicode) throws ServletException, UnsupportedEncodingException { if (node.getNodeType() == 1) { //System.out.println("isEcmaUnicode 2 is : " + isEcmaUnicode); Node text = node.getFirstChild(); String value = ""; if (text != null) { StringBuilder sb = new StringBuilder(); if ("#text".equals(text.getNodeName())) { if (indexXmlList == -1) { firstXmlTagName = node.getNodeName(); itemNameSet.add(firstXmlTagName); indexXmlList++; } if (firstXmlTagName.equals(node.getNodeName())) { xmlRecord = new HashMap(); firstXmlTagParentNode = node.getParentNode(); xmlRecordList.add(xmlRecord); indexXmlList++; } //如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element的值为null if ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) { itemNameSet.add(node.getNodeName()); value = text.getNodeValue(); String oneChar = "";//用于从value中逐个提取字符 if (isEcmaUnicode && (value != null)) { while (value.length() > 0) { if (!value.startsWith("%")) { oneChar = value.substring(0, 1); if ("\n".equals(oneChar)) { //oneChar = ""; oneChar = "#pvo_n#";//替换 } if ("\r".equals(oneChar)) { //oneChar = ""; oneChar = "#pvo_r#";//替换 } sb.append(oneChar); value = value.substring(1); } else if (value.startsWith("%")) { if (value.startsWith("%u")) { oneChar = value.substring(2, 6); oneChar = ByteProcess.UnicodeHexCharsToString(oneChar); if ("\n".equals(oneChar)) { //oneChar = ""; oneChar = "#pvo_n#";//替换 } if ("\r".equals(oneChar)) { //oneChar = ""; oneChar = "#pvo_r#";//替换 } sb.append(oneChar); value = value.substring(6); } else { oneChar = "00" + value.substring(1, 3); oneChar = ByteProcess.UnicodeHexCharsToString(oneChar); if ("\n".equals(oneChar)) { //oneChar = ""; oneChar = "#pvo_n#";//替换 } if ("\r".equals(oneChar)) { //oneChar = ""; oneChar = "#pvo_r#";//替换 } sb.append(oneChar); value = value.substring(3); } } } } String s = sb.toString(); if (s.endsWith("#pvo_r##pvo_n#")) { s = s.substring(0, s.length() - "#pvo_r##pvo_n#".length());//去掉尾部的"#pvo_r##pvo_n#" } if (s.endsWith("#pvo_r#")) { s = s.substring(0, s.length() - "#pvo_r#".length());//去掉尾部的"#pvo_r#" } if (s.endsWith("#pvo_n#")) { s = s.substring(0, s.length() - "#pvo_n#".length());//去掉尾部的"#pvo_n#" } s = this.replace(s, "#pvo_r##pvo_n#", "\r\n");//还原 s = this.replace(s, "#pvo_n#", "\n");//还原 s = this.replace(s, "#pvo_r#", "\r");//还原 ((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), s); } } } else { //叶子结点肯定是字段,但这是一个空值字段 if (indexXmlList == -1) { //throw new ServletException("The first element '<" + node.getNodeName() + ">' could not be null!");//禁止第一个字段为空值 } if (indexXmlList == -1) { //允许第一个字段为空值 firstXmlTagName = node.getNodeName(); itemNameSet.add(firstXmlTagName); indexXmlList++; } if (firstXmlTagName.equals(node.getNodeName())) { xmlRecord = new HashMap(); firstXmlTagParentNode = node.getParentNode(); xmlRecordList.add(xmlRecord); indexXmlList++; } //如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element的值为null if ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) { itemNameSet.add(node.getNodeName()); ((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), "");//用""替代null,还原表单的本义,如果元素存在,request.getParameter('元素名')则肯定会得到字符串,其长度大于等于0;如果元素不存在,request.getParameter('元素名')则肯定得到null } } } NodeList nodeList = node.getChildNodes(); if (nodeList != null && nodeList.getLength() > 0) { for (int i = 0; i < nodeList.getLength(); i++) { Node childNode = nodeList.item(i); visitNode(childNode, isEcmaUnicode); } } return xmlRecordList; }