1.DOM的API说明
image.pngdom原名为Document Object Model ,文档对象模型
可以用 javax.xml.parsers.DocumentBuilderFactory得到DocumentBuilder 实例,然后根据DocumentBuilder的newDocument() 得到Document 实例,也可以DocumentBuilder的parse方法指定解析xml文件得到Document 实例,document 实例的看起来就像是一颗dom节点树
一个dom实例就像一个标准的树结构,每一个节点代表着来自于xml的结构,最常用的节点为text节点和element 节点,使用dom可以创建,移除和改变节点的内容,遍历节点的层级
dom的特点:api使用比sax灵活,可以从dom结构灵活处理dom节点,但是dom的模型是基于内存的,如果有对内存要求比较高的程序可以使用sax这个方式解析,对于复杂的xml一般建议使用dom解析
2.dom的命名空间元素验证以及异常处理
下面的例子,注重理解如何验证xml的命名空间以及xml中的元素验证
然后理解dom的解析的异常处理
创建dom解析器
//得到DocumentBuilderFactory工厂实例
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//得到DocumentBuilder 对象
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
//解析文档
Document document = documentBuilder.parse(xmlFile);
-
xml文件命名空间的验证
第一是否设置要进行验证,setValidating设置为true,表示要验证, 第二个需要给builderFactory设置属性,一个是JAXP_SCHEMA_LANGUAGE ,一个是W3C_XML_SCHEMA 表示是否符合xml语言规范
// "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
static final String JAXP_SCHEMA_LANGUAGE = JAXPConstants.JAXP_SCHEMA_LANGUAGE;
//"http://www.w3.org/2001/XMLSchema";
static final String W3C_XML_SCHEMA =JAXPConstants.W3C_XML_SCHEMA;
//设置解析器在解析文档的时候校验文档
builderFactory.setValidating(true);
//让解析器支持命名空间
builderFactory.setNamespaceAware(true);
//通过指定factory的属性,确定使用Schema进行校验
builderFactory. setAttribute(JAXP_SCHEMA_LANGUAGE,W3C_XML_SCHEMA);
-
xml文件元素的验证
一般来说,写xml的时候需要用到xsd和dtd文件的约束,于是给DocumentBuilderFactory设置具体的属性,来表明具体的xsd和dtd文件在哪,引导程序进行验证就行
// "http://java.sun.com/xml/jaxp/properties/schemaSource";
static final String JAXP_SCHEMA_SOURCE =JAXPConstants.JAXP_SCHEMA_SOURCE;
//设置对该文件进行元素验证,不合法的元素会报错
//方式1
String schemaFileName ="D:\\Eclipse2018Data\\personProject\\jdk\\java-jaxp\\src\\main\\java\\com\\java\\jaxp\\dom\\spring-beans.xsd";
//方式2
File schemaFile = new File(schemaFileName);
//方式3
String[] schemaFileNames = new String[]{schemaFileName};
//setAttribute的value可以是在看字符串,也可以是字符串数组,表示有多个文件约束,也是可以文件的形式
builderFactory.setAttribute(JAXP_SCHEMA_SOURCE, schemaFileName);
还有第二种方式,需要是实现一个EntityResolver接口来进行转换xsd和dtd文件的位置
(详细的例子会在下面全部给出)
public interface EntityResolver {
public abstract InputSource resolveEntity (String publicId,
String systemId)
throws SAXException, IOException;
}
-
解析异常处理
一般需要给DocumentBuilder对象设置错误的解析器
//添加ErrorHandler,将解析的异常手动抛出
documentBuilder.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
System.out.println("warning");
throw exception;
}
private String getParseExceptionInfo(SAXParseException spe) {
String systemId = spe.getSystemId();
if (systemId == null) {
systemId = "null";
}
String info = "URI=" + systemId + " Line=" + spe.getLineNumber() +
": " + spe.getMessage();
return info;
}
@Override
public void error(SAXParseException exception) throws SAXException {
String message = "Error: " + getParseExceptionInfo(exception);
System.out.println(message);
throw new SAXException(message);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
System.out.println("fatal");
throw exception;
}
});
完整的代码如下:
代码实现了xml的命名空间的验证以及xml元素的验证,xml为具有spring-beans的文件,需要准备spring-beans的dtd文件
- 验证的xml文件
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean class="com.java.jaxp.dom.ValidateXmlTest" id="validateXmlTest" >
<property name="sun" value="kang"></property>
<property name="list">
<props>
<prop key="23">234</prop>
</props>
</property>
</bean>
</beans>
- spring-beans.xsd文件
从spring的中jar包取一个出来,这里我就不展示了
- 主程序
/**
* @Project: jdk
* @description: dom的验证xml命名空间
* @author: sunkang
* @create: 2018-10-18 12:57
* @ModificationHistory who when What
**/
public class ValidateXmlTest {
// "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
static final String JAXP_SCHEMA_LANGUAGE = JAXPConstants.JAXP_SCHEMA_LANGUAGE;
//"http://www.w3.org/2001/XMLSchema";
static final String W3C_XML_SCHEMA =JAXPConstants.W3C_XML_SCHEMA;
// "http://java.sun.com/xml/jaxp/properties/schemaSource";
static final String JAXP_SCHEMA_SOURCE =JAXPConstants.JAXP_SCHEMA_SOURCE;
public static void main(String[] args) throws Exception{
//得到DocumentBuilderFactory工厂实例
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//解析文档
//设置解析器在解析文档的时候校验文档
builderFactory.setValidating(true);
//让解析器支持命名空间
builderFactory.setNamespaceAware(true);
//通过指定factory的属性,确定使用Schema进行校验
builderFactory. setAttribute(JAXP_SCHEMA_LANGUAGE,W3C_XML_SCHEMA);
//设置对该文件进行元素验证,不合法的元素会报错
//方式1
String schemaFileName ="D:\\Eclipse2018Data\\personProject\\jdk\\java-jaxp\\src\\main\\java\\com\\java\\jaxp\\dom\\spring-beans.xsd";
//方式2
File schemaFile = new File(schemaFileName);
//方式3
String[] schemaFileNames = new String[]{schemaFileName};
//setAttribute的value可以是在看字符串,也可以是字符串数组,表示有多个文件约束,也是可以文件的形式
// builderFactory.setAttribute(JAXP_SCHEMA_SOURCE, schemaFileName);
//忽略空白
boolean ignoreWhitespace = false;
boolean ignoreComments = false;
boolean putCDATAIntoText = false;
boolean createEntityRefs = false;
builderFactory.setIgnoringComments(ignoreComments);
builderFactory.setIgnoringElementContentWhitespace(ignoreWhitespace);
builderFactory.setCoalescing(putCDATAIntoText);
builderFactory.setExpandEntityReferences(!createEntityRefs);
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
//解析dtd文件
documentBuilder.setEntityResolver(new SpringBeansEntityResolver());
//添加ErrorHandler,将解析的异常手动抛出
documentBuilder.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
System.out.println("warning");
throw exception;
}
private String getParseExceptionInfo(SAXParseException spe) {
String systemId = spe.getSystemId();
if (systemId == null) {
systemId = "null";
}
String info = "URI=" + systemId + " Line=" + spe.getLineNumber() +
": " + spe.getMessage();
return info;
}
@Override
public void error(SAXParseException exception) throws SAXException {
String message = "Error: " + getParseExceptionInfo(exception);
System.out.println(message);
throw new SAXException(message);
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
System.out.println("fatal");
throw exception;
}
});
File xmlFile = new File("D:\\Eclipse2018Data\\personProject\\jdk\\java-jaxp\\src\\main\\java\\com\\java\\jaxp\\dom\\applicationContext.xml");
//解析文档
Document document = documentBuilder.parse(xmlFile);
}
- 第二种xml元素验证方式(主要参考了mybatis 中的org.apache.ibatis.builder.xml.XMLMapperEntityResolver的实现方式)
/**
* @Project: jdk
* @description: 验证xml元素的实体解析器
* @author: sunkang
* @create: 2018-10-18 14:01
* @ModificationHistory who when What
**/
public class SpringBeansEntityResolver implements EntityResolver {
private static final String SPRING_BEANS_SYSTEM = "spring-beans-3.2.xsd";
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
System.out.println("publicId : "+ publicId);
System.out.println("systemId : "+systemId );
//如果这个xsd的资源没有设置绝对路劲之前会是: systemId :http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
if (systemId != null) {
String lowerCaseSystemId = systemId.toLowerCase(Locale.ENGLISH);
if (lowerCaseSystemId.contains(SPRING_BEANS_SYSTEM)) {
return this.getInputSource("org/springframework/beans/factory/xml/spring-beans.xsd", publicId, systemId);
}
}
return null;
}
private InputSource getInputSource(String path, String publicId, String systemId) {
InputSource source = null;
if (path != null) {
try {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
source = new InputSource(in);
source.setPublicId(publicId);
source.setSystemId(systemId);
} catch (Exception var6) {
;
}
}
return source;
}
}
3.dom的元素解析
例子如下,给出beans.xml文件,根据里面的文件内容,把里边的内容平凑成json的形式,然后输出出来
- beans.xml的内容如下:
<beans>
<bean id="bean1" class ="com.java.jaxp.dom">
<property name="username">sunkang</property>
</bean>
<bean id="bean2" class ="com.java.jaxp.dom">
<property name="name">sunkang</property>
</bean>
</beans>
- 解析程序如下:
/**
* @Project: jdk
* @description:
* @author: sunkang
* @create: 2018-10-18 15:18
* @ModificationHistory who when What
**/
public class DomParserDemo {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
String fileName = "D:\\Eclipse2018Data\\personProject\\jdk\\java-jaxp\\src\\main\\java\\com\\java\\jaxp\\dom\\Beans.xml";
File file = new File(fileName);
Document document = documentBuilder.parse(file);
StringBuffer sbf = new StringBuffer();
//解析beans的元素
populateBeans(document, sbf);
System.out.println(sbf.toString());
}
public static void populateBeans(Document document, StringBuffer sbf) {
Element root = document.getDocumentElement();
String beans = root.getTagName();
populateBean(document, sbf);
sbf.append("}");
}
public static void populateBean(Document document, StringBuffer sbf) {
NodeList nodeList = document.getElementsByTagName("bean");
sbf.append("{bean:");
for (int i = 0; i < nodeList.getLength(); i++) {
Element beanElement = (Element) nodeList.item(i);
String id = beanElement.getAttribute("id");
String clazz = beanElement.getAttribute("class");
sbf.append("{id :" + id + ",");
sbf.append("clazz :" + id + ",");
//解析property属性
populateProperty(beanElement, sbf);
if (i != nodeList.getLength() - 1) {
sbf.append("},");
} else {
sbf.append("}");
}
}
sbf.append("}");
}
public static void populateProperty(Element beanElement, StringBuffer sbf) {
NodeList propertyList = beanElement.getElementsByTagName("property");
for (int j = 0; j < propertyList.getLength(); j++) {
Node node = propertyList.item(j);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element property = (Element) node;
String name = property.getAttribute("name");
//获取property的标签的值,下面的这个方法是可以的
//String value = property.getFirstChild().getNodeValue();
String value = property.getTextContent();
sbf.append("property :{name:" + name+ ",");
sbf.append("value:" + value + "}");
}
}
}
}
- 输出结果如下
{bean:{id :bean1,clazz :bean1,property :{name:username,value:sunkang}},{id :bean2,clazz :bean2,property :{name:name,value:sunkang}}}}
网友评论