welcome to xlongwei.com

欢迎大家一起学习、交流、分享


QQ:9167702333 邮箱:admin@xlongwei.com

XMLObject 新增节点属性和空白过滤支持


分类 Java   关键字 分享   标签 java   algorithm   发布 hongwei  1427784744875
注意 转载须保留原文链接,译文链接,作者译者等信息。  
  • 新建节点:new XMLObject(name),可以多次嵌套子节点XMLObject
  • 节点属性:addAttr(attr,value),getAttr(attr)
  • 文本子节点:add(field, value),get(field)
  • 嵌套子节点:add(node),getNode(name),getNodes(name)
  • 复制节点:clone(),update(field, value)
  • 转换xml字符串:toXML(node),fromXML(xml), header()
  • 支持嵌套语法:addNode(name),parent(),addNode(name)会进入下级节点而add(node)不会
  • 支持自关闭语法:<xml attr="value" />

测试样例:
XMLObject xml = new XMLObject("book");
xml.add("author", "Jack");//添加子元素
xml.addAttr("name", "JavaScript");//添加属性
XMLObject store = new XMLObject("store");//添加子节点
store.add("city", "");//支持空元素值
store.addAttr("direction", "east");//子节点添加属性
xml.add(store); //如果要添加多个相似的store子节点,可以clone,update,add(node)
System.out.println(xml.toString());

String string =
new XMLObject("book").addAttr("name", "JavaScript")
.add("author", "Jack")
.addNode("store").addAttr("direction", "east")
.add("city", null) //支持空元素值
.parent() //回到上级节点,可以继续addNode(name)
.toString();
System.out.println(string);
Assert.assertEquals(xml.toString(), string);

xml = XMLObject.fromXML(XMLObject.toXML(xml));
System.out.println(xml.get("author")); //获取元素值
List<XMLObject> nodes = xml.getNodes("store"); //获取所有子节点
for(XMLObject node : nodes) {
System.out.println(node.toString());
}
System.out.println(xml.toString());

String source="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><response platformNo=\"10040011137\"> <service>REGISTER</service> <requestNo>1427707410205</requestNo> <code>1</code> <description>SUCCESS</description></response>";
System.out.println(source);
xml = XMLObject.fromXML(source); //过滤空白
System.out.println(xml);
XMLObject代码:
/**
* @author hongwei
* @date 2015-03-31
*/
public class XMLObject implements Cloneable {
private String name;
private XMLObject parent;//支持链式语法
private List<FieldValue> attrs = new LinkedList<>();//支持属性
private List<Object> nodes = new LinkedList<>();//支持子节点

/**
* @param name 不能包含特殊字符</>
*/
public XMLObject(String name) {
if(name!=null && name.matches("[^</>]+")) {
this.name = name;
}else {
throw new IllegalArgumentException("bad name: "+name);
}
}
public String getName() {
return name;
}
public XMLObject add(String field, String value) {
nodes.add(new FieldValue(field, value));
return this;
}
public XMLObject add(XMLObject node) {
node.parent = this;
nodes.add(node);
return this;
}
public XMLObject addAttr(String attr, String value) {
attrs.add(new FieldValue(attr, value));
return this;
}
public XMLObject addNode(String name) {
XMLObject node = new XMLObject(name);
node.parent = this;
nodes.add(node);
return node;
}
public XMLObject parent() {
return parent;
}
public String get(String field) {
for(Object node : nodes) {
if(node instanceof FieldValue) {
FieldValue fv = (FieldValue)node;
if(fv.getField().equals(field))
return fv.getValue();
}
}
return null;
}
public String getAttr(String attr) {
for(FieldValue fv : attrs) {
if(fv.getField().equals(attr))
return fv.getValue();
}
return null;
}
public XMLObject getNode(String field) {
for(Object node : nodes) {
if(node instanceof XMLObject) {
XMLObject obj = (XMLObject)node;
if(obj.name.equals(field))
return obj;
}
}
return null;
}
public List<XMLObject> getNodes(String field) {
List<XMLObject> objs = new LinkedList<>();
for(Object node : nodes) {
if(node instanceof XMLObject) {
XMLObject obj = (XMLObject)node;
if(obj.name.equals(field))
objs.add(obj);
}
}
return objs;
}

public String toString() {
StringBuilder xml = new StringBuilder("<"+name);
for(FieldValue attr : attrs) {
xml.append(" "+attr.field+"=\""+attr.value+"\"");
}
xml.append('>');
for(Object node : nodes) {
if(node instanceof FieldValue) {
FieldValue fv = (FieldValue)node;
xml.append("<"+fv.field+">");
xml.append(fv.value);
xml.append("</"+fv.field+">");
}else if(node instanceof XMLObject) {
XMLObject obj = (XMLObject)node;
xml.append(obj.toString());
}
}
xml.append("</"+name+">");
return xml.toString();
}

public boolean update(String field, String value) {
for(Object node : nodes) {
if(node instanceof FieldValue) {
FieldValue fv = (FieldValue)node;
if(fv.getField().equals(field)) {
fv.value = value;
return true;
}
}
}
return false;
}
protected XMLObject clone() {
XMLObject xml = new XMLObject(name);
xml.nodes = new LinkedList<>();
for(Object node : this.nodes) {
if(node instanceof FieldValue) {
FieldValue fv = (FieldValue)node;
xml.add(fv.field, fv.value);
}else if(node instanceof XMLObject) {
XMLObject obj = (XMLObject)node;
obj = obj.clone();
xml.add(obj);
}
}
xml.attrs = new LinkedList<>();
for(FieldValue attr : this.attrs) {
xml.addAttr(attr.getField(), attr.getValue());
}
return xml;
}

public static String header() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
}
public static String toXML(XMLObject xml) {
return XMLObject.header()+xml.toString();
}
public static XMLObject fromXML(String xml) {
XMLObject obj = null;
StringBuilder field = new StringBuilder(), value = new StringBuilder();
if(xml.startsWith("<?")) xml = xml.substring(xml.indexOf("?>")+2);
boolean tag = false, start = false;
char[] cs = xml.toCharArray();
for(int i = 0; i<cs.length; i++) {
char c = cs[i];
switch(c) {
case '<':
tag = true;
start = true;
if(field.length()>0 && value.length()==0) {
String fieldWithAttrs = field.toString(), name = null;
int space = fieldWithAttrs.indexOf(' ');
if(space>0) {
name = fieldWithAttrs.substring(0, space);
}else {
name = fieldWithAttrs;
}
int end = xml.indexOf("</"+name+">", i);
String subXml = xml.substring(i-field.length()-2, end+name.length()+3);
XMLObject sub = fromXML(subXml);
obj.add(sub);
i = end+field.length()+3;
field.delete(0, field.length());
}
break;
case '>':
tag = false;
if(start || cs[i-1]=='/') { XMLObject bak = obj; if(cs[i-1]=='/') obj = null; //self close xml
if(obj==null) {
String fieldWithAttrs = field.toString();
int space = fieldWithAttrs.indexOf(' ');
if(space>0) {
obj = new XMLObject(fieldWithAttrs.substring(0, space));
// attr="value"
int equal = fieldWithAttrs.indexOf('=', space);
while(equal>0) {
String attr = fieldWithAttrs.substring(space+1, equal);
int quot1 = fieldWithAttrs.indexOf('"', equal+1);
int quot2 = (quot1>0) ? fieldWithAttrs.indexOf('"', quot1+1) : -1;
String attrValue = (quot1>0 && quot2>0) ? fieldWithAttrs.substring(quot1+1, quot2) : null;
if(attrValue!=null) obj.addAttr(attr, attrValue);

space = fieldWithAttrs.indexOf(' ', quot2+1);
equal = space>0 ? fieldWithAttrs.indexOf('=', space+1) : -1;
}
}else {
obj = new XMLObject(field.toString());
}
field.delete(0, field.length()); if(cs[i-1]=='/' && bak!=null) { //self close xml bak.add(obj); obj = bak; }
}else {
value.delete(0, value.length());//去掉标签之间的空格
}
}else {
if(field.length()>0 && field.length()>0) {
obj.add(field.toString(), value.toString());
field.delete(0, field.length());
value.delete(0, value.length());
}
}
break;
case '/':
start = false;
break;
default:
if(tag && start) field.append(c) ;
if(!tag) value.append(c);
break;
}
}
return obj;
}

public static class FieldValue {
private String field;
private String value;
/**
* @param field 不能包含特殊字符</>
* @param value 不能包含特殊字符</>
*/
public FieldValue(String field, String value) {
if(field!=null && field.length()>0) {
boolean b = field.matches("[^</>]+");
if(b) b = value==null ? true : value.matches("[^</>]*");
else throw new IllegalArgumentException("bad field: "+field);

if(b) { this.field = field; this.value = value==null ? "" : value; }
else throw new IllegalArgumentException("bad value: "+value);
}else {
throw new IllegalArgumentException("bad field: "+field);
}
}
public String getField() {
return field;
}
public String getValue() {
return value;
}
}
}







原文地址: 点此


评论列表