一、介绍
(说明:网络上找到问版本几乎都有问题,不太能用,这里根据实际场景提供如下三种方式)
1、将XML转化为对象
2、将对象转化为XML
3、找到节点后修改节点的值,删除节点,新增自定义的节点等
二、步骤
说明:我们正常形成XML的步骤有两个方向,一是将拼接好XML字符串转化为XML,调用的是dom4j这个依赖:
<!--xml解析工具包-->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.0.0</version>
</dependency>
二是利用对象自动形成XML,如果是不需要进行修改设计的,调用的依赖如下:
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
<将XML转化为对象>
说明:将XML以对象形式进行创建后进行生成,工具方法如下:(将对象写入到指定的文件中)
/**
* 将对象信息保存到xml中
*
* @param entity
* @param file
*/
public static <T> void saveToXml(T entity, String file,String tag) throws Exception {
XStream stream = new XStream(new DomDriver("utf-8"));
stream.autodetectAnnotations(true);
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(StringUtils.isBlank(tag)?XML_TAG_VERSION.getBytes():tag.getBytes());
fileOutputStream.write(System.getProperty("line.separator").getBytes());
stream.toXML(entity, fileOutputStream);
}
//tag为XML的前缀头,XML作为一种可扩展性标记语言,频繁被用于各种通讯报文,其本身的类型和声明也是多样的,此处根据个人需要自己制定xml的标记头
解析:那么应该如何声明与设计XML对象呢?
问答: 在这里我们对XML进行划分,【将每个节点当成一个对象】,【将包裹相似节点的上一级节点当成一个集合】,将【单独标签对为一个节点的节点作为对象属性】,【将标签中的属性声明作为特殊的属性注解】
解析: 图中为我们制定的一个XML模板,通过【saveToXML】我们可以直接生成一个完整的XML,关于其中的注解变量如下:
//变量(对象类,属性均可以转化为XML,不用设置get/set),且默认以标签对形式存放数据
@XmlAccessorType(XmlAccessType.FIELD)
//变量中只有被声明的属性(有get/set)才可以转化为XML
@XmlAccessorType(XmlAccessType.PROPERTY)
//如果属性中引用的是一个接口,需要格外在对象头声明接口的实现类
@XmlJavaTypeAdapter(接口属性的实现类名称.class)
说明: 第二个注解的只会转化哪些拥有get/set方法的属性,除此之外也可以通过注解【@XmlElement】进行声明,
被声明后的注解,即使不使用get/set也可以被创建为XML标签对
(对象的指定)
说明:【XmlAccessorType】开发中我们一般默认使用第一种,全局通用
<BatchExportBusinessEntity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
分析:通常情况下作为一个完整的XML,必然是要有属性说明描述的,我们可以使用如下变量来为节点对象声明属性:
//对象属性(描述xml的空间格式)
@XStreamAsAttribute
@XStreamAlias("xmlns:xsi")
private String xmlspacesName;
//对象属性(描述xml的空间格式)
@XStreamAsAttribute
@XStreamAlias("xmlns:xsd")
private String xmlspaceDesc;
说明:被设置了【@XStreamAsAttribute】注解的属性获取到的值将作为其所在对象代表的节点的节点说明。
@XStreamAlias("DocumentList")
private GradeDocumentVo gradeDocumentVo;
说明:在对象中,我们使用别名,那么在XML节点中其节点名称也为该别名,并且其级别会优先覆盖原对象头别名的声明。也即是说我们对象头上对该节点对象的命名是无效的。
到这里我们可以完全生产出一个单节点的XML文件了,那么如果节点中包含了内节点应该如何处理?
说明:我们将节点作为对象,那么那么节点里面的内节点在父节点对象中应该也是一个属性或引用,而对于内节点本身应该是一个对象。在XML中内节点常见的类型有两种:一种是该内节点为特殊属性的节点,那么直接以对象的形式补充引入即可。一种是该内节点为某种相似的节点并且存在多个,这种情况下我们依旧以单节点作为一个对象,内节点的引用使用List的方式进行引用到其父节点的对象中。
@Data
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("DocumentList")
public class GradeDocumentVo{
@XStreamImplicit
private List<GradeSubBookVo> gradeSubBookVo;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("DocumentExportBusinessEntity") //集合中相似节点的名称
public class GradeSubBookVo{
@XStreamAlias("DocumentName")
private String documentName;
}
说明: 【gradeSubBookVo】的引入为一个内节点,同时也是一个List表示的集合节点。在XML对象文件中表现为:
<DocumentList>
<DocumentExportBusinessEntity>
</DocumentExportBusinessEntity>
<DocumentExportBusinessEntity>
</DocumentExportBusinessEntity>
</DocumentList>
总结:基本上到这里我们可以通过JAVA对象和他们之间的引用关系构建一份合正常的XML。那么如何修改一份XML呢,那么我们需要进一步了解XML转化的基本流程。除了以上方式,dom4j仍然存在着另外一种方式,通过人工拼接XML字符串的形式手工转化为XML。
<方法一>
XmlDocument dom = new XmlDocument();
dom.LoadXml(str);
dom.Save(filepath);
<方法二(来源网络已测)>
public Document changeStringToXML(String sXml)
{
StringReader sr = new StringReader(sXml);
InputSource is = new InputSource(sr);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
return doc;
}
public int writeXML(String path, Document doc)
{
File markFile = new File(path);
OutputStreamWriter outwriter;
try{
outwriter = new OutputStreamWriter(fos, "UTF-8");
Source sorce = new DOMSource(doc);
Result result = new StreamResult(outwriter);
Transformer trans;
try{
trans = TransformerFactory.newInstance().newTransformer();
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
trans.transform(sorce, result);
try{
fos.close();
}
catch (IOException e){
e.printStackTrace();
}
return 0;
}catch (nException e){
e.printStackTrace();
}
}
<方法三(推荐)>
Document document = reader.read(new File(xmlPath));
Element root = document.getRootElement();
Element documentList = root.element("DocumentList");
Document docToElement = DocumentHelper.parseText("<Value/>");
将节点添加到目标节店下面:
documentList.add(docToElement );
获取结集合节点:List<Element> docProperty= documentPropertyList.elements("Property");
获取某个节点的值:String xxxx=el.getText(),"险种类型")
<将XML转化为String>
MemoryStream stream = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(stream, null);
writer.Formatting = Formatting.Indented;
xmlDoc.Save(writer);
StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8);
stream.Position = 0;
string xmlString = sr.ReadToEnd();
sr.Close();
stream.Close();
return xmlString;
说明:对于XML的处理在实际业务场景中要么是自己手动拼接,要么是通过对象生成。而对于一些特殊化节点,则可以通过在 XML文件中找到该节点后,对该节点前后进行增删查改等操作。
Element value = element.element("Value");
element.remove(value);
Document docToElement = DocumentHelper.parseText("<Value/>");
Element elValue =docToElement.getRootElement();
element.add(elValue);
(引入一个新节点)
总结: 在使用过程中发现问题,欢迎上报!