package com.smtscript.lib.xml; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.smtscript.lib.JSStaticXml; import com.smtscript.utils.SMTStatic; public class JSXmlModify { private static class XmlParse { private String _xmlStr; private List _listXmlText = new ArrayList(); private Pattern _patXmlSpace = Pattern.compile("^[\\s\\t\\r\\n ]+"); private Pattern _patXmlBody = Pattern.compile("^[^\\<]+"); private Pattern _patXmlEnd = Pattern.compile("^\\"); private Pattern _patXmlStart = Pattern.compile("^<\\s*([\\w\\:\\-\\.]+)"); private Pattern _patXmlAttr = Pattern.compile("^([\\w\\:\\-]+)(\\s*\\=\\s*\\\")([^\\\"]*)(\\\")"); public JSXMLModifyNode parse(String xmlStr) throws Exception { _xmlStr = xmlStr; JSXMLModifyNode xmlRoot = new JSXMLModifyNode(); xmlRoot.setXmlTextList(_listXmlText); while(parseXmlBlock(null, xmlRoot)) { } return xmlRoot; } private String errXmlStr() { return _xmlStr.length() > 100 ? _xmlStr.substring(0, 100) : _xmlStr; } private boolean cutXmlStr(int length) { String str = _xmlStr.substring(0, length); _xmlStr = _xmlStr.substring(length); _listXmlText.add(str); return _xmlStr.length() > 0; } private boolean parseSpace() { Matcher matSpace = _patXmlSpace.matcher(_xmlStr); if(matSpace.find()) { String space = matSpace.group(0); return cutXmlStr(space.length()); } else if(_xmlStr.length() > 0) return true; else return false; } private boolean parseBody(JSXMLModifyNode parentNode) { Matcher matSpace = _patXmlBody.matcher(_xmlStr); if(matSpace.find()) { String space = matSpace.group(0); JSXMLModifyBody xmlBody = new JSXMLModifyBody(); parentNode.addChildren(xmlBody); xmlBody._valuePos = _listXmlText.size(); return cutXmlStr(space.length()); } else if(_xmlStr.length() > 0) return true; else return false; } public boolean parseXmlBlock(String blockKey, JSXMLModifyNode parentNode) throws Exception { // 读取文本内容 if(!parseBody(parentNode)) return false; // 如果当前段是 if(_xmlStr.startsWith(""); if(pos < 0) throw new Exception("can't find ?> : " + errXmlStr()); return cutXmlStr(pos + 2); } // 如果当前段是 if(_xmlStr.startsWith(""); if(pos < 0) throw new Exception("can't find --> : " + errXmlStr()); return cutXmlStr(pos + 3); } // 如果当前段是 return _xmlStr.length() > 0; case 1: // find : > { while(parseXmlBlock(key, xmlNode)) { } return _xmlStr.length() > 0; } default: break; } } } // 如果不是全局段,且未发现结尾则报错 if(!SMTStatic.isNullOrEmpty(blockKey)) throw new Exception("can't find xml block EOF : " + errXmlStr()); return _xmlStr.length() > 0; } private int parseXmlAttr(JSXMLModifyNode xmlNode) throws Exception { // 去掉前缀空格 if(!parseSpace()) throw new Exception("can't find xml start EOF : " + errXmlStr()); if(_xmlStr.startsWith("/>")) { cutXmlStr(2); return 0; } if(_xmlStr.startsWith(">")) { cutXmlStr(1); // 读取文本 int pos = _xmlStr.indexOf("<"); if(pos < 0) throw new Exception("can't find xml body EOF : " + errXmlStr()); cutXmlStr(pos); JSXMLModifyBody xmlBody = new JSXMLModifyBody(); xmlNode.addChildren(xmlBody); xmlBody._valuePos = _listXmlText.size() - 1; return 1; } Matcher m = _patXmlAttr.matcher(_xmlStr); if(!m.find()) throw new Exception("xml attr not found : " + errXmlStr()); JSXMLModifyAttr xmlAttr = new JSXMLModifyAttr(); xmlNode.addAttr(xmlAttr); _listXmlText.add(m.group(1)); xmlAttr._keyPos = _listXmlText.size() - 1; _listXmlText.add(m.group(2)); _listXmlText.add(m.group(3)); xmlAttr._valuePos = _listXmlText.size() - 1; _listXmlText.add(m.group(4)); _xmlStr = _xmlStr.substring(m.group(0).length()); return 2; } } private JSXMLModifyNode _xmlRoot; //private JSStaticXml _parent; public JSXmlModify(String fileNameOrXmlStr, boolean isFile, JSStaticXml parent) throws Exception { //_parent = parent; String xmlStr = isFile ? SMTStatic.readAllText(fileNameOrXmlStr, "UTF-8") : fileNameOrXmlStr; XmlParse parse = new XmlParse(); _xmlRoot = parse.parse(xmlStr); } public JSXMLModifyNode getFirstXmlNode(String path) { return _xmlRoot.getFirstXmlNode(path); } public String getXmlFullText() { StringBuilder sb = new StringBuilder(); for(String text : _xmlRoot._listXmlText) { sb.append(text); } return sb.toString(); } public void saveXmlFile(String fileName) throws Exception { SMTStatic.saveTextFile(new File(fileName), getXmlFullText(), "UTF-8"); } public boolean setFirstXmlBody(String path, String text) { return _xmlRoot.setFirstXmlBody(path, text); } public boolean setFirstXmlAttr(String path, String attr, String value) { return _xmlRoot.setFirstXmlAttr(path, attr, value); } }