Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

XML文件的解析和写入,语雀浏览链接:https://www.yuque.com/happyflyer/java-topics/sluh3w

NotificationsYou must be signed in to change notification settings

happyflyer/Java-XML

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

1. XML

  • 不同应用程序之间的通信
  • 不同平台间的通信
  • 不同平台间数据的共享
<?xml version="1.0" encoding="UTF-8"?><bookstore>  <bookid="1">    <name>冰与火之歌</name>    <author>乔治马丁</author>    <year>2014</year>    <price>89</price>  </book>  <bookid="2">    <name>安徒生童话</name>    <year>2004</year>    <price>77</price>    <language>English</language>  </book></bookstore>

2. XML 解析

  • DOM
  • SAX
  • DOM4J
  • JDOM

2.1. 应用 DOM 方式解析 XML

DocumentBuilderFactorydbf =DocumentBuilderFactory.newInstance();try {DocumentBuilderdb =dbf.newDocumentBuilder();Documentdocument =db.parse("src/main/resources/books.xml");// ...}catch (ParserConfigurationException |SAXException |IOExceptione) {e.printStackTrace();}
System.out.println("DOM解析开始");NodeListbookList =document.getElementsByTagName("book");for (inti =0;i <bookList.getLength();i++) {NodebookNode =bookList.item(i);NamedNodeMapattrs =bookNode.getAttributes();System.out.println("第" + (i +1) +"本书共有" +attrs.getLength() +"个属性");// ...NodeListchildList =bookNode.getChildNodes();System.out.println("第" + (i +1) +"本书共有" +childList.getLength() +"个子节点");// ...}System.out.println("DOM解析结束");
  • Element
    • nodeName -> element name
    • nodeValue -> null
  • Attribute
    • nodeName -> 属性名称
    • nodeValue -> 属性值
  • Text
    • nodeName -> #text
    • nodeValue -> 节点内容
publicinterfaceNode {publicstaticfinalshortELEMENT_NODE              =1;publicstaticfinalshortATTRIBUTE_NODE            =2;publicstaticfinalshortTEXT_NODE                 =3;// ...}
for (intj =0;j <attrs.getLength();j++) {NodeattrNode =attrs.item(j);System.out.println("第" + (j +1) +"个属性的" +"属性名:" +attrNode.getNodeName()            +",属性值:" +attrNode.getNodeValue());}
ElementbookElement = (Element)bookList.item(i);System.out.println("属性名:id,属性值:" +bookElement.getAttribute("id"));
for (intj =0;j <childList.getLength();j++) {NodechildNode =childList.item(j);if (childNode !=null &&childNode.getNodeType() ==Node.ELEMENT_NODE) {System.out.println("第" + (j +1) +"个子节点的" +"节点名:" +childNode.getNodeName()                +",子节点值:" +childNode.getFirstChild().getNodeValue());    }}
DOM解析开始一共有2本书第1本书共有1个属性第1个属性的属性名id属性值1属性名id属性值1第1本书共有9个子节点第2个子节点的节点名name子节点值冰与火之歌第4个子节点的节点名author子节点值乔治马丁第6个子节点的节点名year子节点值2014第8个子节点的节点名price子节点值89第2本书共有1个属性第1个属性的属性名id属性值2属性名id属性值2第2本书共有9个子节点第2个子节点的节点名name子节点值安徒生童话第4个子节点的节点名year子节点值2004第6个子节点的节点名price子节点值77第8个子节点的节点名language子节点值EnglishDOM解析结束

2.2. 应用 SAX 方式解析 XML

2.2.1. 输出解析内容

SAXParserFactoryspf =SAXParserFactory.newInstance();try {SAXParsersaxParser =spf.newSAXParser();SaxParserHandlerhandler =newSaxParserHandler();saxParser.parse("src/main/resources/books.xml",handler);}catch (ParserConfigurationException |SAXException |IOExceptione) {e.printStackTrace();}
staticclassSaxParserHandlerextendsDefaultHandler {intbookstoreIndex =0;intbookIndex =0;intchildIndex =0;// ...}
@OverridepublicvoidstartDocument()throwsSAXException {super.startDocument();System.out.println("SAX解析开始");}@OverridepublicvoidendDocument()throwsSAXException {super.endDocument();System.out.println("SAX解析结束");}
@OverridepublicvoidstartElement(Stringuri,StringlocalName,StringqName,Attributesattributes)throwsSAXException {super.startElement(uri,localName,qName,attributes);if ("bookstore".equals(qName)) {bookstoreIndex++;bookIndex =0;    }elseif ("book".equals(qName)) {bookIndex++;childIndex =0;System.out.println("第" +bookIndex +"本书共有" +attributes.getLength() +"个属性");for (inti =0;i <attributes.getLength();i++) {System.out.println("第" + (i +1) +"个属性的" +"属性名:" +attributes.getQName(i)                    +",属性值:" +attributes.getValue(i));        }System.out.println("属性名:id,属性值:" +attributes.getValue("id"));    }else {childIndex++;System.out.print("第" +childIndex +"个子节点名:" +qName);    }}
@OverridepublicvoidendElement(Stringuri,StringlocalName,StringqName)throwsSAXException {super.endElement(uri,localName,qName);if ("bookstore".equals(qName)) {System.out.println("一共有" +bookIndex +"本书");    }elseif ("book".equals(qName)) {System.out.println("第" +bookIndex +"本书共有" +childIndex +"个子节点");    }}
@Overridepublicvoidcharacters(char[]ch,intstart,intlength)throwsSAXException {super.characters(ch,start,length);Stringvalue =newString(ch,start,length);if (!"".equals(value.trim())) {System.out.println(",节点值:" +value);    }}
SAX解析开始第1本书共有1个属性第1个属性的属性名id属性值1属性名id属性值1第1个子节点的节点名name节点值冰与火之歌第2个子节点的节点名author节点值乔治马丁第3个子节点的节点名year节点值2014第4个子节点的节点名price节点值89第1本书共有4个子节点第2本书共有1个属性第1个属性的属性名id属性值2属性名id属性值2第1个子节点的节点名name节点值安徒生童话第2个子节点的节点名year节点值2004第3个子节点的节点名price节点值77第4个子节点的节点名language节点值English第2本书共有4个子节点一共有2本书SAX解析结束

2.2.2. 使用 Java 对象保存

publicclassBook {privateStringid;privateStringname;privateStringauthor;privateStringyear;privateStringprice;privateStringlanguage;// ...}
staticclassSaxParserHandlerextendsDefaultHandler {List<Book>bookList =newArrayList<>();intbookIndex =0;Bookbook =null;StringcurrentValue =null;// ...}
@OverridepublicvoidstartElement(Stringuri,StringlocalName,StringqName,Attributesattributes)throwsSAXException {super.startElement(uri,localName,qName,attributes);if ("book".equals(qName)) {bookIndex++;book =newBook();for (inti =0;i <attributes.getLength();i++) {if ("id".equals(attributes.getQName(i))) {book.setId(attributes.getValue(i));            }        }    }}
@OverridepublicvoidendElement(Stringuri,StringlocalName,StringqName)throwsSAXException {super.endElement(uri,localName,qName);if ("book".equals(qName)) {bookList.add(book);book =null;    }elseif ("name".equals(qName)) {book.setName(currentValue);    }elseif ("author".equals(qName)) {book.setAuthor(currentValue);    }elseif ("year".equals(qName)) {book.setYear(currentValue);    }elseif ("price".equals(qName)) {book.setPrice(currentValue);    }elseif ("language".equals(qName)) {book.setLanguage(currentValue);    }}
@Overridepublicvoidcharacters(char[]ch,intstart,intlength)throwsSAXException {super.characters(ch,start,length);currentValue =newString(ch,start,length);}
Book{id='1',name='冰与火之歌',author='乔治马丁',year='2014',price='89',language='null'}Book{id='2',name='安徒生童话',author='null',year='2004',price='77',language='English'}

2.3. 应用 DOM4J 及 JDOM 方式解析 XML

2.3.1. 应用 JDOM 方式解析

SAXBuildersaxBuilder =newSAXBuilder();InputStreamin;try {in =newFileInputStream("src/main/resources/books.xml");InputStreamReaderisr =newInputStreamReader(in,StandardCharsets.UTF_8);Documentdocument =saxBuilder.build(isr);ElementrootElement =document.getRootElement();List<Element>bookList =rootElement.getChildren();// ...}catch (JDOMException |IOExceptione) {e.printStackTrace();}
System.out.println("JDOM解析开始");System.out.println("一共有" +bookList.size() +"本书");for (Elementbook :bookList) {List<Attribute>attributeList =book.getAttributes();System.out.println("第" + (bookList.indexOf(book) +1) +"本书共有"            +attributeList.size() +"个属性");// ...List<Element>childList =book.getChildren();System.out.println("第" + (bookList.indexOf(book) +1) +"本书共有"            +childList.size() +"个子节点");// ...}System.out.println("JDOM解析结束");
List<Attribute>attributeList =book.getAttributes();System.out.println("第" + (bookList.indexOf(book) +1) +"本书共有"        +attributeList.size() +"个属性");for (Attributeattr :attributeList) {System.out.println("第" + (attributeList.indexOf(attr) +1) +"个属性的" +"属性名:" +attr.getName()            +",属性值:" +attr.getValue());}
System.out.println("属性名:id,属性值:" +book.getAttributeValue("id"));
for (Elementchild :childList) {System.out.println("第" + (childList.indexOf(child) +1) +"个子节点的" +"节点名:" +child.getName()            +",子节点值:" +child.getValue());}
JDOM解析开始一共有2本书第1本书共有1个属性第1个属性的属性名id属性值1属性名id属性值1第1本书共有4个子节点第1个子节点的节点名name子节点值冰与火之歌第2个子节点的节点名author子节点值乔治马丁第3个子节点的节点名year子节点值2014第4个子节点的节点名price子节点值89第2本书共有1个属性第1个属性的属性名id属性值2属性名id属性值2第2本书共有4个子节点第1个子节点的节点名name子节点值安徒生童话第2个子节点的节点名year子节点值2004第3个子节点的节点名price子节点值77第4个子节点的节点名language子节点值EnglishJDOM解析结束

2.3.2. 使用 Java 对象保存

SAXBuildersaxBuilder =newSAXBuilder();InputStreamin;List<Book>bookEntityList =newArrayList<>();BookbookEntity =null;try {in =newFileInputStream("src/main/resources/books.xml");Documentdocument =saxBuilder.build(in);ElementrootElement =document.getRootElement();List<Element>bookList =rootElement.getChildren();for (Elementbook :bookList) {bookEntity =newBook();List<Attribute>attributeList =book.getAttributes();for (Attributeattr :attributeList) {if ("id".equals(attr.getName())) {bookEntity.setId(attr.getValue());            }        }List<Element>childList =book.getChildren();for (Elementchild :childList) {if ("name".equals(child.getName())) {bookEntity.setName(child.getValue());            }elseif ("author".equals(child.getName())) {bookEntity.setAuthor(child.getValue());            }elseif ("year".equals(child.getName())) {bookEntity.setYear(child.getValue());            }elseif ("price".equals(child.getName())) {bookEntity.setPrice(child.getValue());            }elseif ("language".equals(child.getName())) {bookEntity.setLanguage(child.getValue());            }        }bookEntityList.add(bookEntity);    }}catch (JDOMException |IOExceptione) {e.printStackTrace();}for (Bookbook :bookEntityList) {System.out.println(book);}

2.3.3. 乱码问题解决

<?xml version="1.0" encoding="ISO-8859-1"?><bookstore>  <bookid="1">    <name>冰与火之歌</name>    <author>乔治马丁</author>    <year>2014</year>    <price>89</price>  </book>  <bookid="2">    <name>安徒生童话</name>    <year>2004</year>    <price>77</price>    <language>English</language>  </book></bookstore>
in =newFileInputStream("src/main/resources/books2.xml");InputStreamReaderisr =newInputStreamReader(in,StandardCharsets.UTF_8);Documentdocument =saxBuilder.build(isr);

2.3.4. 应用 DOM4J 方式解析

SAXReaderreader =newSAXReader();intbookIndex =0;intattributeIndex;intchildIndex;try {Documentdocument =reader.read(newFile("src/main/resources/books.xml"));ElementbookStore =document.getRootElement();Iteratoriterator =bookStore.elementIterator();// ...}catch (DocumentExceptione) {e.printStackTrace();}
System.out.println("DOM4J解析开始");while (iterator.hasNext()) {bookIndex++;attributeIndex =0;childIndex =0;Elementbook = (Element)iterator.next();List<Attribute>bookAttrs =book.attributes();// ...System.out.println("第" +bookIndex +"本书共有" +attributeIndex +"个属性");Iteratoriterator2 =book.elementIterator();// ...System.out.println("第" +bookIndex +"本书共有" +childIndex +"个子节点");}System.out.println("一共有" +bookIndex +"本书");System.out.println("DOM4J解析结束");
for (Attributeattr :bookAttrs) {attributeIndex++;System.out.println("属性名:" +attr.getName()            +",属性值:" +attr.getValue());}
while (iterator2.hasNext()) {childIndex++;ElementbookChild = (Element)iterator2.next();System.out.println("节点名:" +bookChild.getName()            +",节点值:" +bookChild.getStringValue());}
DOM4J解析开始属性名id属性值1第1本书共有1个属性节点名name节点值冰与火之歌节点名author节点值乔治马丁节点名year节点值2014节点名price节点值89第1本书共有4个子节点属性名id属性值2第2本书共有1个属性节点名name节点值安徒生童话节点名year节点值2004节点名price节点值77节点名language节点值English第2本书共有4个子节点一共有2本书DOM4J解析结束

2.4. 四种 XML 解析方式比较

4种XML解析方式比较

2.4.1. DOM

  • 优点
    • 形成了树结构,只管好理解,代码更易编写
    • 解析过程中树结构保留在内存中,方便修改
  • 缺点
    • 当 XML 文件较大时,对内存耗费比较大
    • 容易影响解析性能,造成内存溢出

2.4.2. SAX

  • 优点
    • 采用时间驱动模式,对内存耗费比较小
    • 适用于只需要处理 XML 中数据时
  • 缺点
    • 不易编码
    • 很难同时访问同一个 XML 中多处不同数据

2.4.3. JDOM

  • 仅使用具体类而不使用接口
  • API 大量使用了 Collection 类

2.4.4. DOM4J

  • JDOM 的一种智能分支,它合并了许多超出基本 XML 文档表示的功能
  • DOM4J 使用接口和抽象基本类方法,是一个优秀的 Java XML API
  • 具有性能优异、灵活性好、功能强大、极端易用的特点
  • 是一个开放源代码的软件

3. XML 生成

3.1. 通过 DOM 方式生成 XML 文档

DocumentBuildergetDocumentBuilder() {DocumentBuilderFactorydbf =DocumentBuilderFactory.newInstance();DocumentBuilderdb =null;try {db =dbf.newDocumentBuilder();    }catch (ParserConfigurationExceptione) {e.printStackTrace();    }returndb;}
TransformergetTransformer() {TransformerFactorytff =TransformerFactory.newInstance();Transformertf =null;try {tf =tff.newTransformer();tf.setOutputProperty(OutputKeys.INDENT,"yes");    }catch (TransformerConfigurationExceptione) {e.printStackTrace();    }returntf;}
publicvoidcreateXml() {Documentdocument =getDocumentBuilder().newDocument();document.setXmlStandalone(true);Elementbookstore =document.createElement("bookstore");Elementbook =document.createElement("book");book.setAttribute("id","1");Elementname =document.createElement("name");name.setTextContent("小王子");book.appendChild(name);bookstore.appendChild(book);document.appendChild(bookstore);Transformertf =getTransformer();try {tf.transform(newDOMSource(document),newStreamResult(newFile("src/main/resources/books3.xml")        ));    }catch (TransformerExceptione) {e.printStackTrace();    }}

3.2. 通过 SAX 方式生成 XML 文档

TransformerHandlergetTransformerHandler() {SAXTransformerFactorytff = (SAXTransformerFactory)SAXTransformerFactory.newInstance();TransformerHandlerhandler =null;try {handler =tff.newTransformerHandler();    }catch (TransformerConfigurationExceptione) {e.printStackTrace();    }returnhandler;}
List<Book>bookList =parseXml();TransformerHandlerhandler =getTransformerHandler();Transformertf =handler.getTransformer();tf.setOutputProperty(OutputKeys.ENCODING,"UTF-8");tf.setOutputProperty(OutputKeys.INDENT,"yes");try {Filef =newFile("src/main/resources/books4.xml");if (!f.exists()) {f.createNewFile();    }Resultresult =newStreamResult(newFileOutputStream(f));handler.setResult(result);handler.startDocument();AttributesImplattr =newAttributesImpl();handler.startElement("","","bookstore",attr);for (Bookbook :bookList) {attr.clear();attr.addAttribute("","","id","","1");handler.startElement("","","book",attr);// ...handler.endElement("","","book");    }handler.endElement("","","bookstore");handler.endDocument();}catch (SAXException |IOExceptione) {e.printStackTrace();}
if (book.getAuthor() !=null && !"".equals(book.getAuthor().trim())) {attr.clear();handler.startElement("","","author",attr);handler.characters(book.getAuthor().toCharArray(),0,book.getAuthor().length());handler.endElement("","","author");}

3.3. 通过 JDOM 方式生成 XML 文档

Elementrss =newElement("rss");rss.setAttribute("version","2.0");Documentdocument =newDocument(rss);Elementchannel =newElement("channel");rss.addContent(channel);Elementtitle =newElement("title");title.setText("国内最新新闻");channel.addContent(title);Elementtitle2 =newElement("title2");title2.setText("<尖括号会自动转义>");channel.addContent(title2);Formatformat =Format.getCompactFormat();format.setIndent("");format.setEncoding("GBK");XMLOutputteroutput =newXMLOutputter(format);try {output.output(document,newFileOutputStream("src/main/resources/rssNews1.xml"));}catch (IOExceptione) {e.printStackTrace();}

3.4. 通过 DOM4J 方式生成 XML 文档

Documentdocument =DocumentHelper.createDocument();Elementrss =document.addElement("rss");rss.addAttribute("version","2.0");Elementchannel =rss.addElement("channel");Elementtitle =channel.addElement("title");title.setText("国内最新新闻");Elementtitle2 =channel.addElement("title2");title2.setText("<尖括号不会自动转义>");OutputFormatformat =OutputFormat.createPrettyPrint();format.setEncoding("GBK");Filefile =newFile("src/main/resources/rssNews2.xml");try {XMLWriterwriter =newXMLWriter(newFileOutputStream(file),format);writer.setEscapeText(false);writer.write(document);writer.close();}catch (IOExceptione) {e.printStackTrace();}

3.5. 四种 XML 生成方式比较

  • DOM:基于 tree
  • SAX:基于事件
  • JDOM 和 DOM4J:基于底层 API

DOM和SAX的比较


[8]ページ先頭

©2009-2025 Movatter.jp