美文网首页
(3) Dom(Document Object Model)解析

(3) Dom(Document Object Model)解析

作者: Mrsunup | 来源:发表于2018-10-24 20:56 被阅读0次

1.DOM的API说明

image.png

dom原名为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}}}}

相关文章

  • iOS网络数据解析之XML解析

    XML解析常见的两种方式:DOM解析和SAX解析 DOM解析 DOM:Document Object Model(...

  • 使用SAX读写XML文档

    DOM、SAX和JAXP解析 XML文档解析方式 DOM:Document Object Model:即文档对象模...

  • xml文件的解析

    一、XML解析的两种方式 1、DOM方式   DOM:Document Object Model,这种方式是W3C...

  • JAVA基础-XML的解析(二)

    三、XML的解析 XML的解析一共有2种方式:DOM解析:(DOM:Document Object Model)S...

  • 解析XML

    解析方式 DOM MAC提供的解析方法 (Document Object Model ,文档对象模型。解析时需要...

  • ddu-xml

    一、DOM解析XML 我们首先来看看DOM(Document Object Model)这种方式解析xml,通过D...

  • (3) Dom(Document Object Model)解析

    1.DOM的API说明 dom原名为Document Object Model ,文档对象模型 可以用 javax...

  • XML解析——DOM方式

    XML解析方式:DOM:(Document Object Model)文档对象模型。SAX:(Simple API...

  • 简述网页的渲染机制

    DOM:Document Object Model,浏览器将HTML解析成树形的数据结构,简称DOM。CSSOM:...

  • 浏览器渲染机制

    DOM:Document Object Model,浏览器将HTML解析成树形的数据结构,简称DOM。CSSOM:...

网友评论

      本文标题:(3) Dom(Document Object Model)解析

      本文链接:https://www.haomeiwen.com/subject/nsoxtqtx.html