活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

掌握XML DOM编程技巧的在线学习指南 从基础入门到高级应用全面解析XML文档对象模型

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-25 01:00:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

XML(可扩展标记语言)作为一种通用的数据交换格式,在软件开发、Web服务和数据存储中扮演着重要角色。而XML DOM(文档对象模型)则是与XML文档交互的关键接口,它允许开发者通过编程方式读取、修改、创建和操作XML文档。本指南将带您从基础入门到高级应用,全面掌握XML DOM编程技巧,无论您是初学者还是有经验的开发者,都能从中获得实用的知识和技能。

XML DOM基础

什么是XML DOM?

XML DOM是一种平台和语言中立的接口,它允许程序和脚本动态访问和更新XML文档的内容、结构和样式。DOM将XML文档表示为一个树形结构,其中每个节点都是文档中的一个对象,可以通过JavaScript、Python、Java等编程语言进行操作。

DOM树结构

在DOM中,XML文档被表示为一个层次结构的树,包含以下主要节点类型:

• 文档节点(Document):整个文档的根节点
• 元素节点(Element):XML元素,如<book>,<author>
• 属性节点(Attribute):元素的属性,如id="book1"
• 文本节点(Text):元素中的文本内容
• 注释节点(Comment):XML文档中的注释

例如,以下简单的XML文档:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <bookstore>
  3.   <book category="fiction">
  4.     <title lang="en">Harry Potter</title>
  5.     <author>J.K. Rowling</author>
  6.     <year>2005</year>
  7.     <price>29.99</price>
  8.   </book>
  9. </bookstore>
复制代码

在DOM中表示为以下树结构:
  1. Document
  2. └── Element: bookstore
  3.       └── Element: book (attribute: category="fiction")
  4.            ├── Element: title (attribute: lang="en")
  5.            │    └── Text: Harry Potter
  6.            ├── Element: author
  7.            │    └── Text: J.K. Rowling
  8.            ├── Element: year
  9.            │    └── Text: 2005
  10.            └── Element: price
  11.                 └── Text: 29.99
复制代码

环境设置

浏览器环境

在Web浏览器中,XML DOM API是内置的,无需额外安装。您可以直接在JavaScript中使用这些API:
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <title>XML DOM 示例</title>
  5. </head>
  6. <body>
  7.     <script>
  8.         // XML DOM代码将在这里编写
  9.     </script>
  10. </body>
  11. </html>
复制代码

Node.js环境

在Node.js中,您可以使用内置的xmldom模块或第三方库如libxmljs:
  1. npm install xmldom
复制代码
  1. const { DOMParser } = require('xmldom');
  2. // 或者使用其他库
  3. const libxmljs = require('libxmljs');
复制代码

Python环境

在Python中,您可以使用内置的xml.dom模块:
  1. from xml.dom.minidom import parse, parseString
  2. # 或者使用更强大的lxml库
  3. from lxml import etree
复制代码

Java环境

在Java中,您可以使用内置的JAXP API:
  1. import javax.xml.parsers.DocumentBuilder;
  2. import javax.xml.parsers.DocumentBuilderFactory;
  3. import org.w3c.dom.Document;
复制代码

基础操作

加载XML文档
  1. // 从字符串加载XML
  2. const xmlString = `
  3. <bookstore>
  4.   <book category="fiction">
  5.     <title>Harry Potter</title>
  6.     <author>J.K. Rowling</author>
  7.     <year>2005</year>
  8.     <price>29.99</price>
  9.   </book>
  10. </bookstore>
  11. `;
  12. const parser = new DOMParser();
  13. const xmlDoc = parser.parseFromString(xmlString, "text/xml");
  14. // 从文件加载XML(在浏览器中)
  15. fetch('books.xml')
  16.   .then(response => response.text())
  17.   .then(str => {
  18.     const xmlDoc = new DOMParser().parseFromString(str, "text/xml");
  19.     // 处理XML文档
  20.   });
复制代码
  1. # 从字符串加载XML
  2. xml_string = """
  3. <bookstore>
  4.   <book category="fiction">
  5.     <title>Harry Potter</title>
  6.     <author>J.K. Rowling</author>
  7.     <year>2005</year>
  8.     <price>29.99</price>
  9.   </book>
  10. </bookstore>
  11. """
  12. # 使用minidom
  13. from xml.dom.minidom import parseString
  14. doc = parseString(xml_string)
  15. # 使用lxml
  16. from lxml import etree
  17. tree = etree.fromstring(xml_string.encode())
复制代码
  1. // 从字符串加载XML
  2. String xmlString = "<bookstore><book category="fiction"><title>Harry Potter</title>...</book></bookstore>";
  3. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  4. DocumentBuilder builder = factory.newDocumentBuilder();
  5. Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
  6. // 从文件加载XML
  7. File file = new File("books.xml");
  8. Document doc = builder.parse(file);
复制代码

遍历XML文档
  1. // 获取根元素
  2. const rootElement = xmlDoc.documentElement;
  3. console.log("Root element:", rootElement.nodeName);
  4. // 获取所有book元素
  5. const books = rootElement.getElementsByTagName("book");
  6. console.log("Found", books.length, "books");
  7. // 遍历所有book元素
  8. for (let i = 0; i < books.length; i++) {
  9.     const book = books[i];
  10.    
  11.     // 获取属性
  12.     const category = book.getAttribute("category");
  13.     console.log("Book category:", category);
  14.    
  15.     // 获取子元素
  16.     const title = book.getElementsByTagName("title")[0];
  17.     const author = book.getElementsByTagName("author")[0];
  18.     const year = book.getElementsByTagName("year")[0];
  19.     const price = book.getElementsByTagName("price")[0];
  20.    
  21.     // 获取文本内容
  22.     console.log("Title:", title.textContent);
  23.     console.log("Author:", author.textContent);
  24.     console.log("Year:", year.textContent);
  25.     console.log("Price:", price.textContent);
  26. }
复制代码
  1. # 使用minidom遍历
  2. root = doc.documentElement
  3. print(f"Root element: {root.tagName}")
  4. books = root.getElementsByTagName("book")
  5. print(f"Found {books.length} books")
  6. for i in range(books.length):
  7.     book = books[i]
  8.    
  9.     # 获取属性
  10.     category = book.getAttribute("category")
  11.     print(f"Book category: {category}")
  12.    
  13.     # 获取子元素
  14.     title = book.getElementsByTagName("title")[0]
  15.     author = book.getElementsByTagName("author")[0]
  16.     year = book.getElementsByTagName("year")[0]
  17.     price = book.getElementsByTagName("price")[0]
  18.    
  19.     # 获取文本内容
  20.     print(f"Title: {title.firstChild.data}")
  21.     print(f"Author: {author.firstChild.data}")
  22.     print(f"Year: {year.firstChild.data}")
  23.     print(f"Price: {price.firstChild.data}")
复制代码
  1. // 获取根元素
  2. Element rootElement = doc.getDocumentElement();
  3. System.out.println("Root element: " + rootElement.getNodeName());
  4. // 获取所有book元素
  5. NodeList books = rootElement.getElementsByTagName("book");
  6. System.out.println("Found " + books.getLength() + " books");
  7. for (int i = 0; i < books.getLength(); i++) {
  8.     Element book = (Element) books.item(i);
  9.    
  10.     // 获取属性
  11.     String category = book.getAttribute("category");
  12.     System.out.println("Book category: " + category);
  13.    
  14.     // 获取子元素
  15.     Element title = (Element) book.getElementsByTagName("title").item(0);
  16.     Element author = (Element) book.getElementsByTagName("author").item(0);
  17.     Element year = (Element) book.getElementsByTagName("year").item(0);
  18.     Element price = (Element) book.getElementsByTagName("price").item(0);
  19.    
  20.     // 获取文本内容
  21.     System.out.println("Title: " + title.getTextContent());
  22.     System.out.println("Author: " + author.getTextContent());
  23.     System.out.println("Year: " + year.getTextContent());
  24.     System.out.println("Price: " + price.getTextContent());
  25. }
复制代码

节点操作

创建新节点
  1. // 创建新book元素
  2. const newBook = xmlDoc.createElement("book");
  3. newBook.setAttribute("category", "non-fiction");
  4. // 创建子元素
  5. const title = xmlDoc.createElement("title");
  6. title.textContent = "The Art of Programming";
  7. newBook.appendChild(title);
  8. const author = xmlDoc.createElement("author");
  9. author.textContent = "Donald Knuth";
  10. newBook.appendChild(author);
  11. const year = xmlDoc.createElement("year");
  12. year.textContent = "1997";
  13. newBook.appendChild(year);
  14. const price = xmlDoc.createElement("price");
  15. price.textContent = "49.99";
  16. newBook.appendChild(price);
  17. // 将新book添加到bookstore
  18. xmlDoc.documentElement.appendChild(newBook);
  19. // 输出修改后的XML
  20. console.log(new XMLSerializer().serializeToString(xmlDoc));
复制代码
  1. # 使用minidom创建新节点
  2. new_book = doc.createElement("book")
  3. new_book.setAttribute("category", "non-fiction")
  4. # 创建子元素
  5. title = doc.createElement("title")
  6. title.appendChild(doc.createTextNode("The Art of Programming"))
  7. new_book.appendChild(title)
  8. author = doc.createElement("author")
  9. author.appendChild(doc.createTextNode("Donald Knuth"))
  10. new_book.appendChild(author)
  11. year = doc.createElement("year")
  12. year.appendChild(doc.createTextNode("1997"))
  13. new_book.appendChild(year)
  14. price = doc.createElement("price")
  15. price.appendChild(doc.createTextNode("49.99"))
  16. new_book.appendChild(price)
  17. # 将新book添加到bookstore
  18. doc.documentElement.appendChild(new_book)
  19. # 输出修改后的XML
  20. print(doc.toprettyxml(indent="  "))
复制代码
  1. // 创建新book元素
  2. Element newBook = doc.createElement("book");
  3. newBook.setAttribute("category", "non-fiction");
  4. // 创建子元素
  5. Element title = doc.createElement("title");
  6. title.setTextContent("The Art of Programming");
  7. newBook.appendChild(title);
  8. Element author = doc.createElement("author");
  9. author.setTextContent("Donald Knuth");
  10. newBook.appendChild(author);
  11. Element year = doc.createElement("year");
  12. year.setTextContent("1997");
  13. newBook.appendChild(year);
  14. Element price = doc.createElement("price");
  15. price.setTextContent("49.99");
  16. newBook.appendChild(price);
  17. // 将新book添加到bookstore
  18. doc.getDocumentElement().appendChild(newBook);
  19. // 输出修改后的XML
  20. TransformerFactory transformerFactory = TransformerFactory.newInstance();
  21. Transformer transformer = transformerFactory.newTransformer();
  22. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  23. DOMSource source = new DOMSource(doc);
  24. StreamResult result = new StreamResult(new StringWriter());
  25. transformer.transform(source, result);
  26. System.out.println(result.getWriter().toString());
复制代码

修改节点
  1. // 获取第一本书
  2. const firstBook = xmlDoc.getElementsByTagName("book")[0];
  3. // 修改价格
  4. const priceElement = firstBook.getElementsByTagName("price")[0];
  5. priceElement.textContent = "24.99";
  6. // 修改category属性
  7. firstBook.setAttribute("category", "fantasy");
  8. // 输出修改后的XML
  9. console.log(new XMLSerializer().serializeToString(xmlDoc));
复制代码
  1. # 使用minidom修改节点
  2. first_book = doc.getElementsByTagName("book")[0]
  3. # 修改价格
  4. price_element = first_book.getElementsByTagName("price")[0]
  5. price_element.firstChild.data = "24.99"
  6. # 修改category属性
  7. first_book.setAttribute("category", "fantasy")
  8. # 输出修改后的XML
  9. print(doc.toprettyxml(indent="  "))
复制代码
  1. // 获取第一本书
  2. Element firstBook = (Element) doc.getElementsByTagName("book").item(0);
  3. // 修改价格
  4. Element priceElement = (Element) firstBook.getElementsByTagName("price").item(0);
  5. priceElement.setTextContent("24.99");
  6. // 修改category属性
  7. firstBook.setAttribute("category", "fantasy");
  8. // 输出修改后的XML
  9. TransformerFactory transformerFactory = TransformerFactory.newInstance();
  10. Transformer transformer = transformerFactory.newTransformer();
  11. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  12. DOMSource source = new DOMSource(doc);
  13. StreamResult result = new StreamResult(new StringWriter());
  14. transformer.transform(source, result);
  15. System.out.println(result.getWriter().toString());
复制代码

删除节点
  1. // 获取第一本书
  2. const firstBook = xmlDoc.getElementsByTagName("book")[0];
  3. // 删除year元素
  4. const yearElement = firstBook.getElementsByTagName("year")[0];
  5. firstBook.removeChild(yearElement);
  6. // 或者删除整个book节点
  7. // xmlDoc.documentElement.removeChild(firstBook);
  8. // 输出修改后的XML
  9. console.log(new XMLSerializer().serializeToString(xmlDoc));
复制代码
  1. # 使用minidom删除节点
  2. first_book = doc.getElementsByTagName("book")[0]
  3. # 删除year元素
  4. year_element = first_book.getElementsByTagName("year")[0]
  5. first_book.removeChild(year_element)
  6. # 或者删除整个book节点
  7. # doc.documentElement.removeChild(first_book)
  8. # 输出修改后的XML
  9. print(doc.toprettyxml(indent="  "))
复制代码
  1. // 获取第一本书
  2. Element firstBook = (Element) doc.getElementsByTagName("book").item(0);
  3. // 删除year元素
  4. Element yearElement = (Element) firstBook.getElementsByTagName("year").item(0);
  5. firstBook.removeChild(yearElement);
  6. // 或者删除整个book节点
  7. // doc.getDocumentElement().removeChild(firstBook);
  8. // 输出修改后的XML
  9. TransformerFactory transformerFactory = TransformerFactory.newInstance();
  10. Transformer transformer = transformerFactory.newTransformer();
  11. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  12. DOMSource source = new DOMSource(doc);
  13. StreamResult result = new StreamResult(new StringWriter());
  14. transformer.transform(source, result);
  15. System.out.println(result.getWriter().toString());
复制代码

属性处理

获取和设置属性
  1. // 获取第一本书
  2. const firstBook = xmlDoc.getElementsByTagName("book")[0];
  3. // 获取category属性
  4. const category = firstBook.getAttribute("category");
  5. console.log("Category:", category);
  6. // 设置新属性
  7. firstBook.setAttribute("isbn", "978-0596006522");
  8. // 检查属性是否存在
  9. if (firstBook.hasAttribute("category")) {
  10.     console.log("Category attribute exists");
  11. }
  12. // 删除属性
  13. firstBook.removeAttribute("category");
  14. // 获取所有属性
  15. const attributes = firstBook.attributes;
  16. for (let i = 0; i < attributes.length; i++) {
  17.     const attr = attributes[i];
  18.     console.log(`${attr.name}: ${attr.value}`);
  19. }
  20. // 输出修改后的XML
  21. console.log(new XMLSerializer().serializeToString(xmlDoc));
复制代码
  1. # 使用minidom处理属性
  2. first_book = doc.getElementsByTagName("book")[0]
  3. # 获取category属性
  4. category = first_book.getAttribute("category")
  5. print(f"Category: {category}")
  6. # 设置新属性
  7. first_book.setAttribute("isbn", "978-0596006522")
  8. # 检查属性是否存在
  9. if first_book.hasAttribute("category"):
  10.     print("Category attribute exists")
  11. # 删除属性
  12. first_book.removeAttribute("category")
  13. # 获取所有属性
  14. attributes = first_book.attributes
  15. for i in range(attributes.length):
  16.     attr = attributes.item(i)
  17.     print(f"{attr.name}: {attr.value}")
  18. # 输出修改后的XML
  19. print(doc.toprettyxml(indent="  "))
复制代码
  1. // 获取第一本书
  2. Element firstBook = (Element) doc.getElementsByTagName("book").item(0);
  3. // 获取category属性
  4. String category = firstBook.getAttribute("category");
  5. System.out.println("Category: " + category);
  6. // 设置新属性
  7. firstBook.setAttribute("isbn", "978-0596006522");
  8. // 检查属性是否存在
  9. if (firstBook.hasAttribute("category")) {
  10.     System.out.println("Category attribute exists");
  11. }
  12. // 删除属性
  13. firstBook.removeAttribute("category");
  14. // 获取所有属性
  15. NamedNodeMap attributes = firstBook.getAttributes();
  16. for (int i = 0; i < attributes.getLength(); i++) {
  17.     Node attr = attributes.item(i);
  18.     System.out.println(attr.getNodeName() + ": " + attr.getNodeValue());
  19. }
  20. // 输出修改后的XML
  21. TransformerFactory transformerFactory = TransformerFactory.newInstance();
  22. Transformer transformer = transformerFactory.newTransformer();
  23. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  24. DOMSource source = new DOMSource(doc);
  25. StreamResult result = new StreamResult(new StringWriter());
  26. transformer.transform(source, result);
  27. System.out.println(result.getWriter().toString());
复制代码

高级查询

使用XPath

XPath是一种在XML文档中查找信息的语言,它提供了强大的查询能力。
  1. // 在浏览器中使用XPath
  2. function evaluateXPath(xmlDoc, xpath) {
  3.     const result = xmlDoc.evaluate(xpath, xmlDoc, null, XPathResult.ANY_TYPE, null);
  4.     const nodes = [];
  5.     let node = result.iterateNext();
  6.     while (node) {
  7.         nodes.push(node);
  8.         node = result.iterateNext();
  9.     }
  10.     return nodes;
  11. }
  12. // 查询所有category为fiction的book
  13. const fictionBooks = evaluateXPath(xmlDoc, "//book[@category='fiction']");
  14. console.log("Found", fictionBooks.length, "fiction books");
  15. // 查询所有价格大于25的book
  16. const expensiveBooks = evaluateXPath(xmlDoc, "//book[price > 25]");
  17. console.log("Found", expensiveBooks.length, "expensive books");
  18. // 查询所有author为J.K. Rowling的book的title
  19. const titles = evaluateXPath(xmlDoc, "//book[author='J.K. Rowling']/title");
  20. console.log("Found", titles.length, "titles by J.K. Rowling");
  21. titles.forEach(title => console.log(title.textContent));
复制代码
  1. # 使用lxml进行XPath查询
  2. from lxml import etree
  3. # 解析XML
  4. tree = etree.fromstring(xml_string.encode())
  5. # 查询所有category为fiction的book
  6. fiction_books = tree.xpath("//book[@category='fiction']")
  7. print(f"Found {len(fiction_books)} fiction books")
  8. # 查询所有价格大于25的book
  9. expensive_books = tree.xpath("//book[price > 25]")
  10. print(f"Found {len(expensive_books)} expensive books")
  11. # 查询所有author为J.K. Rowling的book的title
  12. titles = tree.xpath("//book[author='J.K. Rowling']/title")
  13. print(f"Found {len(titles)} titles by J.K. Rowling")
  14. for title in titles:
  15.     print(title.text)
复制代码
  1. // 使用XPath进行查询
  2. import javax.xml.xpath.*;
  3. // 创建XPath工厂
  4. XPathFactory xPathFactory = XPathFactory.newInstance();
  5. XPath xpath = xPathFactory.newXPath();
  6. try {
  7.     // 查询所有category为fiction的book
  8.     XPathExpression expr = xpath.compile("//book[@category='fiction']");
  9.     NodeList fictionBooks = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
  10.     System.out.println("Found " + fictionBooks.getLength() + " fiction books");
  11.    
  12.     // 查询所有价格大于25的book
  13.     expr = xpath.compile("//book[price > 25]");
  14.     NodeList expensiveBooks = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
  15.     System.out.println("Found " + expensiveBooks.getLength() + " expensive books");
  16.    
  17.     // 查询所有author为J.K. Rowling的book的title
  18.     expr = xpath.compile("//book[author='J.K. Rowling']/title");
  19.     NodeList titles = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
  20.     System.out.println("Found " + titles.getLength() + " titles by J.K. Rowling");
  21.     for (int i = 0; i < titles.getLength(); i++) {
  22.         System.out.println(titles.item(i).getTextContent());
  23.     }
  24. } catch (XPathExpressionException e) {
  25.     e.printStackTrace();
  26. }
复制代码

使用XSLT转换

XSLT(可扩展样式表语言转换)是一种用于将XML文档转换为其他格式(如HTML、XML或文本)的语言。
  1. // XSLT转换示例
  2. const xsltString = `
  3. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  4.   <xsl:template match="/">
  5.     <html>
  6.       <body>
  7.         <h2>Bookstore</h2>
  8.         <table border="1">
  9.           <tr bgcolor="#9acd32">
  10.             <th>Title</th>
  11.             <th>Author</th>
  12.             <th>Year</th>
  13.             <th>Price</th>
  14.           </tr>
  15.           <xsl:for-each select="bookstore/book">
  16.             <tr>
  17.               <td><xsl:value-of select="title"/></td>
  18.               <td><xsl:value-of select="author"/></td>
  19.               <td><xsl:value-of select="year"/></td>
  20.               <td><xsl:value-of select="price"/></td>
  21.             </tr>
  22.           </xsl:for-each>
  23.         </table>
  24.       </body>
  25.     </html>
  26.   </xsl:template>
  27. </xsl:stylesheet>
  28. `;
  29. // 创建XSLT文档
  30. const xsltDoc = new DOMParser().parseFromString(xsltString, "text/xml");
  31. // 创建XSLT处理器
  32. const xsltProcessor = new XSLTProcessor();
  33. xsltProcessor.importStylesheet(xsltDoc);
  34. // 执行转换
  35. const resultDoc = xsltProcessor.transformToDocument(xmlDoc);
  36. // 转换为HTML字符串
  37. const resultHtml = new XMLSerializer().serializeToString(resultDoc);
  38. console.log(resultHtml);
  39. // 或者直接将结果显示在页面上
  40. document.body.innerHTML = resultHtml;
复制代码
  1. # 使用lxml进行XSLT转换
  2. from lxml import etree
  3. # 解析XML和XSLT
  4. xml_tree = etree.fromstring(xml_string.encode())
  5. xslt_string = """
  6. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  7.   <xsl:template match="/">
  8.     <html>
  9.       <body>
  10.         <h2>Bookstore</h2>
  11.         <table border="1">
  12.           <tr bgcolor="#9acd32">
  13.             <th>Title</th>
  14.             <th>Author</th>
  15.             <th>Year</th>
  16.             <th>Price</th>
  17.           </tr>
  18.           <xsl:for-each select="bookstore/book">
  19.             <tr>
  20.               <td><xsl:value-of select="title"/></td>
  21.               <td><xsl:value-of select="author"/></td>
  22.               <td><xsl:value-of select="year"/></td>
  23.               <td><xsl:value-of select="price"/></td>
  24.             </tr>
  25.           </xsl:for-each>
  26.         </table>
  27.       </body>
  28.     </html>
  29.   </xsl:template>
  30. </xsl:stylesheet>
  31. """
  32. xslt_tree = etree.fromstring(xslt_string.encode())
  33. # 创建转换器
  34. transform = etree.XSLT(xslt_tree)
  35. # 执行转换
  36. result_tree = transform(xml_tree)
  37. # 输出结果
  38. print(str(result_tree))
  39. # 或者保存到文件
  40. with open('bookstore.html', 'wb') as f:
  41.     f.write(etree.tostring(result_tree, pretty_print=True))
复制代码
  1. // 使用XSLT进行转换
  2. import javax.xml.transform.*;
  3. import javax.xml.transform.stream.*;
  4. try {
  5.     // XSLT字符串
  6.     String xsltString = "<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\n" +
  7.             "  <xsl:template match="/">\n" +
  8.             "    <html>\n" +
  9.             "      <body>\n" +
  10.             "        <h2>Bookstore</h2>\n" +
  11.             "        <table border="1">\n" +
  12.             "          <tr bgcolor="#9acd32">\n" +
  13.             "            <th>Title</th>\n" +
  14.             "            <th>Author</th>\n" +
  15.             "            <th>Year</th>\n" +
  16.             "            <th>Price</th>\n" +
  17.             "          </tr>\n" +
  18.             "          <xsl:for-each select="bookstore/book">\n" +
  19.             "            <tr>\n" +
  20.             "              <td><xsl:value-of select="title"/></td>\n" +
  21.             "              <td><xsl:value-of select="author"/></td>\n" +
  22.             "              <td><xsl:value-of select="year"/></td>\n" +
  23.             "              <td><xsl:value-of select="price"/></td>\n" +
  24.             "            </tr>\n" +
  25.             "          </xsl:for-each>\n" +
  26.             "        </table>\n" +
  27.             "      </body>\n" +
  28.             "    </html>\n" +
  29.             "  </xsl:template>\n" +
  30.             "</xsl:stylesheet>";
  31.     // 创建XSLT源
  32.     Source xsltSource = new StreamSource(new StringReader(xsltString));
  33.    
  34.     // 创建转换器工厂
  35.     TransformerFactory transformerFactory = TransformerFactory.newInstance();
  36.    
  37.     // 创建转换器
  38.     Transformer transformer = transformerFactory.newTransformer(xsltSource);
  39.    
  40.     // 设置输出属性
  41.     transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  42.    
  43.     // 创建XML源
  44.     Source xmlSource = new DOMSource(doc);
  45.    
  46.     // 创建结果
  47.     StringWriter resultWriter = new StringWriter();
  48.     Result result = new StreamResult(resultWriter);
  49.    
  50.     // 执行转换
  51.     transformer.transform(xmlSource, result);
  52.    
  53.     // 输出结果
  54.     System.out.println(resultWriter.toString());
  55.    
  56.     // 或者保存到文件
  57.     try (FileWriter fileWriter = new FileWriter("bookstore.html")) {
  58.         transformer.transform(xmlSource, new StreamResult(fileWriter));
  59.     }
  60. } catch (TransformerException | IOException e) {
  61.     e.printStackTrace();
  62. }
复制代码

错误处理

处理解析错误
  1. // 处理解析错误
  2. function parseXml(xmlString) {
  3.     try {
  4.         const parser = new DOMParser();
  5.         const xmlDoc = parser.parseFromString(xmlString, "text/xml");
  6.         
  7.         // 检查解析错误
  8.         const parserError = xmlDoc.getElementsByTagName("parsererror")[0];
  9.         if (parserError) {
  10.             throw new Error("XML parsing error: " + parserError.textContent);
  11.         }
  12.         
  13.         return xmlDoc;
  14.     } catch (error) {
  15.         console.error("Error parsing XML:", error.message);
  16.         return null;
  17.     }
  18. }
  19. // 测试错误的XML
  20. const invalidXml = "<bookstore><book><title>Missing closing tag</book></bookstore>";
  21. const xmlDoc = parseXml(invalidXml);
  22. if (!xmlDoc) {
  23.     console.log("Failed to parse XML");
  24. } else {
  25.     console.log("XML parsed successfully");
  26. }
复制代码
  1. # 使用minidom处理解析错误
  2. from xml.dom.minidom import parseString
  3. from xml.parsers.expat import ExpatError
  4. def parse_xml(xml_string):
  5.     try:
  6.         doc = parseString(xml_string)
  7.         return doc
  8.     except ExpatError as e:
  9.         print(f"XML parsing error: {e}")
  10.         return None
  11. # 测试错误的XML
  12. invalid_xml = "<bookstore><book><title>Missing closing tag</book></bookstore>"
  13. doc = parse_xml(invalid_xml)
  14. if doc is None:
  15.     print("Failed to parse XML")
  16. else:
  17.     print("XML parsed successfully")
复制代码
  1. // 处理解析错误
  2. public Document parseXml(String xmlString) {
  3.     try {
  4.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  5.         DocumentBuilder builder = factory.newDocumentBuilder();
  6.         
  7.         // 创建错误处理器
  8.         builder.setErrorHandler(new ErrorHandler() {
  9.             @Override
  10.             public void warning(SAXParseException e) throws SAXException {
  11.                 System.out.println("Warning: " + e.getMessage());
  12.             }
  13.             
  14.             @Override
  15.             public void error(SAXParseException e) throws SAXException {
  16.                 System.out.println("Error: " + e.getMessage());
  17.                 throw e;
  18.             }
  19.             
  20.             @Override
  21.             public void fatalError(SAXParseException e) throws SAXException {
  22.                 System.out.println("Fatal error: " + e.getMessage());
  23.                 throw e;
  24.             }
  25.         });
  26.         
  27.         InputSource is = new InputSource(new StringReader(xmlString));
  28.         return builder.parse(is);
  29.     } catch (ParserConfigurationException | SAXException | IOException e) {
  30.         System.err.println("Error parsing XML: " + e.getMessage());
  31.         return null;
  32.     }
  33. }
  34. // 测试错误的XML
  35. String invalidXml = "<bookstore><book><title>Missing closing tag</book></bookstore>";
  36. Document doc = parseXml(invalidXml);
  37. if (doc == null) {
  38.     System.out.println("Failed to parse XML");
  39. } else {
  40.     System.out.println("XML parsed successfully");
  41. }
复制代码

处理XPath错误
  1. // 处理XPath错误
  2. function safeEvaluateXPath(xmlDoc, xpath) {
  3.     try {
  4.         const result = xmlDoc.evaluate(xpath, xmlDoc, null, XPathResult.ANY_TYPE, null);
  5.         const nodes = [];
  6.         let node = result.iterateNext();
  7.         while (node) {
  8.             nodes.push(node);
  9.             node = result.iterateNext();
  10.         }
  11.         return nodes;
  12.     } catch (error) {
  13.         console.error("Error evaluating XPath:", error.message);
  14.         return [];
  15.     }
  16. }
  17. // 测试无效的XPath
  18. const nodes = safeEvaluateXPath(xmlDoc, "//book[@category='fiction' && price > 25]");
  19. if (nodes.length === 0) {
  20.     console.log("No nodes found or error occurred");
  21. }
复制代码
  1. # 使用lxml处理XPath错误
  2. def safe_xpath_query(xml_tree, xpath):
  3.     try:
  4.         return xml_tree.xpath(xpath)
  5.     except etree.XPathError as e:
  6.         print(f"XPath error: {e}")
  7.         return []
  8. # 测试无效的XPath
  9. tree = etree.fromstring(xml_string.encode())
  10. nodes = safe_xpath_query(tree, "//book[@category='fiction' && price > 25]")
  11. if not nodes:
  12.     print("No nodes found or error occurred")
复制代码
  1. // 处理XPath错误
  2. public NodeList safeXPathEvaluate(Document doc, String xpath) {
  3.     try {
  4.         XPathFactory xPathFactory = XPathFactory.newInstance();
  5.         XPath xpathObj = xPathFactory.newXPath();
  6.         XPathExpression expr = xpathObj.compile(xpath);
  7.         return (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
  8.     } catch (XPathExpressionException e) {
  9.         System.err.println("Error evaluating XPath: " + e.getMessage());
  10.         return null;
  11.     }
  12. }
  13. // 测试无效的XPath
  14. NodeList nodes = safeXPathEvaluate(doc, "//book[@category='fiction' && price > 25]");
  15. if (nodes == null || nodes.getLength() == 0) {
  16.     System.out.println("No nodes found or error occurred");
  17. }
复制代码

性能优化

使用SAX解析器处理大型XML文件

DOM解析器将整个XML文档加载到内存中,对于大型文件可能效率低下。SAX(Simple API for XML)是一种事件驱动的解析方式,更适合处理大型XML文件。
  1. import org.xml.sax.Attributes;
  2. import org.xml.sax.SAXException;
  3. import org.xml.sax.helpers.DefaultHandler;
  4. import javax.xml.parsers.SAXParser;
  5. import javax.xml.parsers.SAXParserFactory;
  6. import java.io.ByteArrayInputStream;
  7. import java.io.InputStream;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. // 定义Book类
  11. class Book {
  12.     private String category;
  13.     private String title;
  14.     private String author;
  15.     private String year;
  16.     private String price;
  17.    
  18.     // 构造函数、getter和setter方法
  19.     public Book() {}
  20.    
  21.     public String getCategory() { return category; }
  22.     public void setCategory(String category) { this.category = category; }
  23.    
  24.     public String getTitle() { return title; }
  25.     public void setTitle(String title) { this.title = title; }
  26.    
  27.     public String getAuthor() { return author; }
  28.     public void setAuthor(String author) { this.author = author; }
  29.    
  30.     public String getYear() { return year; }
  31.     public void setYear(String year) { this.year = year; }
  32.    
  33.     public String getPrice() { return price; }
  34.     public void setPrice(String price) { this.price = price; }
  35. }
  36. // SAX处理器
  37. class BookHandler extends DefaultHandler {
  38.     private List<Book> books = new ArrayList<>();
  39.     private Book currentBook;
  40.     private String currentElement;
  41.    
  42.     @Override
  43.     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  44.         currentElement = qName;
  45.         
  46.         if ("book".equals(qName)) {
  47.             currentBook = new Book();
  48.             currentBook.setCategory(attributes.getValue("category"));
  49.         }
  50.     }
  51.    
  52.     @Override
  53.     public void characters(char[] ch, int start, int length) throws SAXException {
  54.         String value = new String(ch, start, length).trim();
  55.         
  56.         if (value.isEmpty()) {
  57.             return;
  58.         }
  59.         
  60.         if (currentBook != null) {
  61.             switch (currentElement) {
  62.                 case "title":
  63.                     currentBook.setTitle(value);
  64.                     break;
  65.                 case "author":
  66.                     currentBook.setAuthor(value);
  67.                     break;
  68.                 case "year":
  69.                     currentBook.setYear(value);
  70.                     break;
  71.                 case "price":
  72.                     currentBook.setPrice(value);
  73.                     break;
  74.             }
  75.         }
  76.     }
  77.    
  78.     @Override
  79.     public void endElement(String uri, String localName, String qName) throws SAXException {
  80.         if ("book".equals(qName)) {
  81.             books.add(currentBook);
  82.             currentBook = null;
  83.         }
  84.         currentElement = null;
  85.     }
  86.    
  87.     public List<Book> getBooks() {
  88.         return books;
  89.     }
  90. }
  91. // 使用SAX解析XML
  92. public List<Book> parseXmlWithSax(String xmlString) {
  93.     try {
  94.         SAXParserFactory factory = SAXParserFactory.newInstance();
  95.         SAXParser saxParser = factory.newSAXParser();
  96.         
  97.         BookHandler handler = new BookHandler();
  98.         InputStream inputStream = new ByteArrayInputStream(xmlString.getBytes());
  99.         saxParser.parse(inputStream, handler);
  100.         
  101.         return handler.getBooks();
  102.     } catch (Exception e) {
  103.         System.err.println("Error parsing XML with SAX: " + e.getMessage());
  104.         return null;
  105.     }
  106. }
  107. // 测试SAX解析
  108. String xmlString = "<bookstore><book category="fiction"><title>Harry Potter</title><author>J.K. Rowling</author><year>2005</year><price>29.99</price></book></bookstore>";
  109. List<Book> books = parseXmlWithSax(xmlString);
  110. if (books != null) {
  111.     for (Book book : books) {
  112.         System.out.println("Title: " + book.getTitle());
  113.         System.out.println("Author: " + book.getAuthor());
  114.         System.out.println("Year: " + book.getYear());
  115.         System.out.println("Price: " + book.getPrice());
  116.         System.out.println("Category: " + book.getCategory());
  117.         System.out.println("-------------------");
  118.     }
  119. }
复制代码

使用XPath进行高效查询

XPath提供了高效的查询方式,可以避免手动遍历整个DOM树。
  1. // 使用XPath进行高效查询
  2. function queryXmlWithXPath(xmlDoc, xpath) {
  3.     const start = performance.now();
  4.    
  5.     const result = xmlDoc.evaluate(xpath, xmlDoc, null, XPathResult.ANY_TYPE, null);
  6.     const nodes = [];
  7.     let node = result.iterateNext();
  8.     while (node) {
  9.         nodes.push(node);
  10.         node = result.iterateNext();
  11.     }
  12.    
  13.     const end = performance.now();
  14.     console.log(`XPath query took ${end - start} milliseconds`);
  15.    
  16.     return nodes;
  17. }
  18. // 测试XPath查询
  19. const books = queryXmlWithXPath(xmlDoc, "//book[price > 25]");
  20. console.log(`Found ${books.length} books with price > 25`);
复制代码
  1. # 使用lxml的XPath进行高效查询
  2. import time
  3. def query_xml_with_xpath(xml_tree, xpath):
  4.     start_time = time.time()
  5.    
  6.     nodes = xml_tree.xpath(xpath)
  7.    
  8.     end_time = time.time()
  9.     print(f"XPath query took {end_time - start_time} seconds")
  10.    
  11.     return nodes
  12. # 测试XPath查询
  13. tree = etree.fromstring(xml_string.encode())
  14. books = query_xml_with_xpath(tree, "//book[price > 25]")
  15. print(f"Found {len(books)} books with price > 25")
复制代码
  1. // 使用XPath进行高效查询
  2. public NodeList queryXmlWithXPath(Document doc, String xpath) {
  3.     long startTime = System.currentTimeMillis();
  4.    
  5.     try {
  6.         XPathFactory xPathFactory = XPathFactory.newInstance();
  7.         XPath xpathObj = xPathFactory.newXPath();
  8.         XPathExpression expr = xpathObj.compile(xpath);
  9.         NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
  10.         
  11.         long endTime = System.currentTimeMillis();
  12.         System.out.println("XPath query took " + (endTime - startTime) + " milliseconds");
  13.         
  14.         return nodes;
  15.     } catch (XPathExpressionException e) {
  16.         System.err.println("Error evaluating XPath: " + e.getMessage());
  17.         return null;
  18.     }
  19. }
  20. // 测试XPath查询
  21. NodeList books = queryXmlWithXPath(doc, "//book[price > 25]");
  22. if (books != null) {
  23.     System.out.println("Found " + books.getLength() + " books with price > 25");
  24. }
复制代码

缓存XPath表达式

如果需要多次使用相同的XPath表达式,可以缓存编译后的表达式以提高性能。
  1. import javax.xml.xpath.*;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public class XPathCache {
  5.     private static final Map<String, XPathExpression> cache = new HashMap<>();
  6.     private static final XPath xpath = XPathFactory.newInstance().newXPath();
  7.    
  8.     public static XPathExpression compile(String xpathExpression) throws XPathExpressionException {
  9.         XPathExpression expr = cache.get(xpathExpression);
  10.         if (expr == null) {
  11.             expr = xpath.compile(xpathExpression);
  12.             cache.put(xpathExpression, expr);
  13.         }
  14.         return expr;
  15.     }
  16.    
  17.     public static void clearCache() {
  18.         cache.clear();
  19.     }
  20. }
  21. // 使用缓存的XPath表达式
  22. public NodeList queryWithCachedXPath(Document doc, String xpath) {
  23.     long startTime = System.currentTimeMillis();
  24.    
  25.     try {
  26.         XPathExpression expr = XPathCache.compile(xpath);
  27.         NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
  28.         
  29.         long endTime = System.currentTimeMillis();
  30.         System.out.println("Cached XPath query took " + (endTime - startTime) + " milliseconds");
  31.         
  32.         return nodes;
  33.     } catch (XPathExpressionException e) {
  34.         System.err.println("Error evaluating XPath: " + e.getMessage());
  35.         return null;
  36.     }
  37. }
  38. // 测试缓存的XPath查询
  39. for (int i = 0; i < 10; i++) {
  40.     NodeList books = queryWithCachedXPath(doc, "//book[price > 25]");
  41.     System.out.println("Found " + (books != null ? books.getLength() : 0) + " books with price > 25");
  42. }
复制代码

实际应用

XML配置文件处理

XML常用于配置文件,以下是一个处理应用程序配置文件的示例。
  1. import org.w3c.dom.*;
  2. import javax.xml.parsers.*;
  3. import java.io.File;
  4. public class ConfigManager {
  5.     private Document configDoc;
  6.    
  7.     public ConfigManager(String configFilePath) throws Exception {
  8.         File configFile = new File(configFilePath);
  9.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  10.         DocumentBuilder builder = factory.newDocumentBuilder();
  11.         configDoc = builder.parse(configFile);
  12.         configDoc.getDocumentElement().normalize();
  13.     }
  14.    
  15.     public String getDatabaseUrl() {
  16.         NodeList dbNodes = configDoc.getElementsByTagName("database");
  17.         if (dbNodes.getLength() > 0) {
  18.             Element dbElement = (Element) dbNodes.item(0);
  19.             return dbElement.getAttribute("url");
  20.         }
  21.         return null;
  22.     }
  23.    
  24.     public String getDatabaseUsername() {
  25.         NodeList dbNodes = configDoc.getElementsByTagName("database");
  26.         if (dbNodes.getLength() > 0) {
  27.             Element dbElement = (Element) dbNodes.item(0);
  28.             return dbElement.getAttribute("username");
  29.         }
  30.         return null;
  31.     }
  32.    
  33.     public String getDatabasePassword() {
  34.         NodeList dbNodes = configDoc.getElementsByTagName("database");
  35.         if (dbNodes.getLength() > 0) {
  36.             Element dbElement = (Element) dbNodes.item(0);
  37.             return dbElement.getAttribute("password");
  38.         }
  39.         return null;
  40.     }
  41.    
  42.     public boolean isDebugMode() {
  43.         NodeList debugNodes = configDoc.getElementsByTagName("debug");
  44.         if (debugNodes.getLength() > 0) {
  45.             Element debugElement = (Element) debugNodes.item(0);
  46.             return Boolean.parseBoolean(debugElement.getAttribute("enabled"));
  47.         }
  48.         return false;
  49.     }
  50.    
  51.     public int getMaxConnections() {
  52.         NodeList connNodes = configDoc.getElementsByTagName("connections");
  53.         if (connNodes.getLength() > 0) {
  54.             Element connElement = (Element) connNodes.item(0);
  55.             return Integer.parseInt(connElement.getAttribute("max"));
  56.         }
  57.         return 10; // 默认值
  58.     }
  59.    
  60.     public static void main(String[] args) {
  61.         try {
  62.             ConfigManager config = new ConfigManager("config.xml");
  63.             
  64.             System.out.println("Database URL: " + config.getDatabaseUrl());
  65.             System.out.println("Database Username: " + config.getDatabaseUsername());
  66.             System.out.println("Database Password: " + config.getDatabasePassword());
  67.             System.out.println("Debug Mode: " + config.isDebugMode());
  68.             System.out.println("Max Connections: " + config.getMaxConnections());
  69.         } catch (Exception e) {
  70.             e.printStackTrace();
  71.         }
  72.     }
  73. }
复制代码

对应的配置文件示例 (config.xml):
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <config>
  3.     <database url="jdbc:mysql://localhost:3306/myapp" username="admin" password="secret" />
  4.     <debug enabled="true" />
  5.     <connections max="20" />
  6. </config>
复制代码

RSS新闻阅读器

RSS是一种基于XML的格式,用于分发经常更新的内容,如新闻标题。以下是一个简单的RSS新闻阅读器示例。
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <title>RSS News Reader</title>
  5.     <style>
  6.         body {
  7.             font-family: Arial, sans-serif;
  8.             max-width: 800px;
  9.             margin: 0 auto;
  10.             padding: 20px;
  11.         }
  12.         .news-item {
  13.             border-bottom: 1px solid #eee;
  14.             padding: 15px 0;
  15.         }
  16.         .news-title {
  17.             font-size: 18px;
  18.             font-weight: bold;
  19.             margin-bottom: 5px;
  20.         }
  21.         .news-title a {
  22.             color: #0066cc;
  23.             text-decoration: none;
  24.         }
  25.         .news-title a:hover {
  26.             text-decoration: underline;
  27.         }
  28.         .news-date {
  29.             color: #666;
  30.             font-size: 12px;
  31.             margin-bottom: 10px;
  32.         }
  33.         .news-description {
  34.             color: #333;
  35.             line-height: 1.5;
  36.         }
  37.         .loading {
  38.             text-align: center;
  39.             padding: 20px;
  40.             color: #666;
  41.         }
  42.         .error {
  43.             color: #c00;
  44.             padding: 10px;
  45.             background-color: #ffeeee;
  46.             border: 1px solid #ffcccc;
  47.             margin-bottom: 20px;
  48.         }
  49.     </style>
  50. </head>
  51. <body>
  52.     <h1>RSS News Reader</h1>
  53.     <div id="news-container">
  54.         <div class="loading">Loading news...</div>
  55.     </div>
  56.     <script>
  57.         // RSS URL
  58.         const rssUrl = 'https://rss.cnn.com/rss/edition.rss';
  59.         
  60.         // 获取新闻容器
  61.         const newsContainer = document.getElementById('news-container');
  62.         
  63.         // 获取RSS数据
  64.         fetch(rssUrl)
  65.             .then(response => response.text())
  66.             .then(str => {
  67.                 // 解析XML
  68.                 const parser = new DOMParser();
  69.                 const xmlDoc = parser.parseFromString(str, "text/xml");
  70.                
  71.                 // 检查解析错误
  72.                 const parserError = xmlDoc.getElementsByTagName("parsererror")[0];
  73.                 if (parserError) {
  74.                     throw new Error("XML parsing error: " + parserError.textContent);
  75.                 }
  76.                
  77.                 // 获取所有新闻项
  78.                 const items = xmlDoc.getElementsByTagName("item");
  79.                
  80.                 // 清空容器
  81.                 newsContainer.innerHTML = '';
  82.                
  83.                 // 如果没有新闻项
  84.                 if (items.length === 0) {
  85.                     newsContainer.innerHTML = '<div class="error">No news items found.</div>';
  86.                     return;
  87.                 }
  88.                
  89.                 // 显示新闻项
  90.                 for (let i = 0; i < items.length; i++) {
  91.                     const item = items[i];
  92.                     
  93.                     // 获取标题
  94.                     const titleElement = item.getElementsByTagName("title")[0];
  95.                     const title = titleElement ? titleElement.textContent : 'No title';
  96.                     
  97.                     // 获取链接
  98.                     const linkElement = item.getElementsByTagName("link")[0];
  99.                     const link = linkElement ? linkElement.textContent : '#';
  100.                     
  101.                     // 获取日期
  102.                     const dateElement = item.getElementsByTagName("pubDate")[0];
  103.                     const date = dateElement ? new Date(dateElement.textContent).toLocaleString() : '';
  104.                     
  105.                     // 获取描述
  106.                     const descriptionElement = item.getElementsByTagName("description")[0];
  107.                     const description = descriptionElement ? descriptionElement.textContent : '';
  108.                     
  109.                     // 创建新闻项HTML
  110.                     const newsItem = document.createElement('div');
  111.                     newsItem.className = 'news-item';
  112.                     newsItem.innerHTML = `
  113.                         <div class="news-title"><a href="${link}" target="_blank">${title}</a></div>
  114.                         <div class="news-date">${date}</div>
  115.                         <div class="news-description">${description}</div>
  116.                     `;
  117.                     
  118.                     // 添加到容器
  119.                     newsContainer.appendChild(newsItem);
  120.                 }
  121.             })
  122.             .catch(error => {
  123.                 console.error('Error fetching RSS:', error);
  124.                 newsContainer.innerHTML = `<div class="error">Error loading news: ${error.message}</div>`;
  125.             });
  126.     </script>
  127. </body>
  128. </html>
复制代码

XML数据导出和导入

以下是一个使用XML DOM导出和导入数据的示例,适用于数据备份和迁移。
  1. import xml.dom.minidom as minidom
  2. import xml.etree.ElementTree as ET
  3. import json
  4. import csv
  5. import os
  6. class DataExporter:
  7.     def __init__(self):
  8.         pass
  9.    
  10.     def export_to_xml(self, data, filename):
  11.         """
  12.         将数据导出为XML文件
  13.         :param data: 要导出的数据,应为字典列表
  14.         :param filename: 输出文件名
  15.         """
  16.         try:
  17.             # 创建XML文档
  18.             doc = minidom.Document()
  19.             
  20.             # 创建根元素
  21.             root = doc.createElement("data")
  22.             doc.appendChild(root)
  23.             
  24.             # 为每个数据项创建元素
  25.             for item in data:
  26.                 record = doc.createElement("record")
  27.                
  28.                 # 为每个字段创建子元素
  29.                 for key, value in item.items():
  30.                     field = doc.createElement(key)
  31.                     field.appendChild(doc.createTextNode(str(value)))
  32.                     record.appendChild(field)
  33.                
  34.                 root.appendChild(record)
  35.             
  36.             # 写入文件
  37.             with open(filename, 'w', encoding='utf-8') as f:
  38.                 f.write(doc.toprettyxml(indent="  "))
  39.             
  40.             print(f"数据已成功导出到 {filename}")
  41.             return True
  42.         except Exception as e:
  43.             print(f"导出XML时出错: {e}")
  44.             return False
  45.    
  46.     def import_from_xml(self, filename):
  47.         """
  48.         从XML文件导入数据
  49.         :param filename: 输入文件名
  50.         :return: 导入的数据(字典列表)
  51.         """
  52.         try:
  53.             # 解析XML文件
  54.             tree = ET.parse(filename)
  55.             root = tree.getroot()
  56.             
  57.             data = []
  58.             
  59.             # 遍历所有record元素
  60.             for record in root.findall('record'):
  61.                 item = {}
  62.                
  63.                 # 遍历record的所有子元素
  64.                 for field in record:
  65.                     item[field.tag] = field.text
  66.                
  67.                 data.append(item)
  68.             
  69.             print(f"成功从 {filename} 导入 {len(data)} 条记录")
  70.             return data
  71.         except Exception as e:
  72.             print(f"导入XML时出错: {e}")
  73.             return []
  74.    
  75.     def export_to_json(self, data, filename):
  76.         """
  77.         将数据导出为JSON文件
  78.         :param data: 要导出的数据
  79.         :param filename: 输出文件名
  80.         """
  81.         try:
  82.             with open(filename, 'w', encoding='utf-8') as f:
  83.                 json.dump(data, f, indent=2, ensure_ascii=False)
  84.             print(f"数据已成功导出到 {filename}")
  85.             return True
  86.         except Exception as e:
  87.             print(f"导出JSON时出错: {e}")
  88.             return False
  89.    
  90.     def import_from_json(self, filename):
  91.         """
  92.         从JSON文件导入数据
  93.         :param filename: 输入文件名
  94.         :return: 导入的数据
  95.         """
  96.         try:
  97.             with open(filename, 'r', encoding='utf-8') as f:
  98.                 data = json.load(f)
  99.             print(f"成功从 {filename} 导入 {len(data)} 条记录")
  100.             return data
  101.         except Exception as e:
  102.             print(f"导入JSON时出错: {e}")
  103.             return []
  104.    
  105.     def export_to_csv(self, data, filename):
  106.         """
  107.         将数据导出为CSV文件
  108.         :param data: 要导出的数据(字典列表)
  109.         :param filename: 输出文件名
  110.         """
  111.         try:
  112.             if not data:
  113.                 print("没有数据可导出")
  114.                 return False
  115.             
  116.             # 获取所有字段名
  117.             fieldnames = data[0].keys()
  118.             
  119.             with open(filename, 'w', newline='', encoding='utf-8') as f:
  120.                 writer = csv.DictWriter(f, fieldnames=fieldnames)
  121.                 writer.writeheader()
  122.                 writer.writerows(data)
  123.             
  124.             print(f"数据已成功导出到 {filename}")
  125.             return True
  126.         except Exception as e:
  127.             print(f"导出CSV时出错: {e}")
  128.             return False
  129.    
  130.     def import_from_csv(self, filename):
  131.         """
  132.         从CSV文件导入数据
  133.         :param filename: 输入文件名
  134.         :return: 导入的数据(字典列表)
  135.         """
  136.         try:
  137.             data = []
  138.             with open(filename, 'r', encoding='utf-8') as f:
  139.                 reader = csv.DictReader(f)
  140.                 for row in reader:
  141.                     data.append(dict(row))
  142.             
  143.             print(f"成功从 {filename} 导入 {len(data)} 条记录")
  144.             return data
  145.         except Exception as e:
  146.             print(f"导入CSV时出错: {e}")
  147.             return []
  148.    
  149.     def convert_format(self, input_file, output_file, input_format, output_format):
  150.         """
  151.         转换数据格式
  152.         :param input_file: 输入文件名
  153.         :param output_file: 输出文件名
  154.         :param input_format: 输入格式(xml, json, csv)
  155.         :param output_format: 输出格式(xml, json, csv)
  156.         """
  157.         # 根据输入格式导入数据
  158.         if input_format.lower() == 'xml':
  159.             data = self.import_from_xml(input_file)
  160.         elif input_format.lower() == 'json':
  161.             data = self.import_from_json(input_file)
  162.         elif input_format.lower() == 'csv':
  163.             data = self.import_from_csv(input_file)
  164.         else:
  165.             print(f"不支持的输入格式: {input_format}")
  166.             return False
  167.         
  168.         if not data:
  169.             print("未能导入数据,转换失败")
  170.             return False
  171.         
  172.         # 根据输出格式导出数据
  173.         if output_format.lower() == 'xml':
  174.             return self.export_to_xml(data, output_file)
  175.         elif output_format.lower() == 'json':
  176.             return self.export_to_json(data, output_file)
  177.         elif output_format.lower() == 'csv':
  178.             return self.export_to_csv(data, output_file)
  179.         else:
  180.             print(f"不支持的输出格式: {output_format}")
  181.             return False
  182. # 示例使用
  183. if __name__ == "__main__":
  184.     # 创建示例数据
  185.     sample_data = [
  186.         {"id": 1, "name": "John Doe", "email": "john@example.com", "age": 30},
  187.         {"id": 2, "name": "Jane Smith", "email": "jane@example.com", "age": 25},
  188.         {"id": 3, "name": "Bob Johnson", "email": "bob@example.com", "age": 40}
  189.     ]
  190.    
  191.     # 创建导出器实例
  192.     exporter = DataExporter()
  193.    
  194.     # 导出为XML
  195.     exporter.export_to_xml(sample_data, "data.xml")
  196.    
  197.     # 导出为JSON
  198.     exporter.export_to_json(sample_data, "data.json")
  199.    
  200.     # 导出为CSV
  201.     exporter.export_to_csv(sample_data, "data.csv")
  202.    
  203.     # 从XML导入
  204.     imported_data = exporter.import_from_xml("data.xml")
  205.     print("从XML导入的数据:", imported_data)
  206.    
  207.     # 转换格式(XML转JSON)
  208.     exporter.convert_format("data.xml", "data_from_xml.json", "xml", "json")
  209.    
  210.     # 转换格式(CSV转XML)
  211.     exporter.convert_format("data.csv", "data_from_csv.xml", "csv", "xml")
复制代码

学习资源

在线教程和文档

1. MDN Web Docs - XML DOM链接:https://developer.mozilla.org/en-US/docs/Web/API/XML_DOM描述: Mozilla开发者网络提供的XML DOM文档,包含详细的API参考和示例。
2. 链接:https://developer.mozilla.org/en-US/docs/Web/API/XML_DOM
3. 描述: Mozilla开发者网络提供的XML DOM文档,包含详细的API参考和示例。
4. W3Schools - XML DOM Tutorial链接:https://www.w3schools.com/xml/dom_intro.asp描述: 提供XML DOM基础教程,适合初学者入门。
5. 链接:https://www.w3schools.com/xml/dom_intro.asp
6. 描述: 提供XML DOM基础教程,适合初学者入门。
7. Java XML Documentation链接:https://docs.oracle.com/javase/tutorial/jaxp/index.html描述: Oracle官方Java XML处理教程,包括DOM、SAX和XSLT。
8. 链接:https://docs.oracle.com/javase/tutorial/jaxp/index.html
9. 描述: Oracle官方Java XML处理教程,包括DOM、SAX和XSLT。
10. Python XML Processing Documentation链接:https://docs.python.org/3/library/xml.dom.html描述: Python官方文档中关于XML DOM处理的部分。
11. 链接:https://docs.python.org/3/library/xml.dom.html
12. 描述: Python官方文档中关于XML DOM处理的部分。
13. XPath Tutorial by W3Schools链接:https://www.w3schools.com/xml/xpath_intro.asp描述: XPath语言的基础教程,包含大量示例。
14. 链接:https://www.w3schools.com/xml/xpath_intro.asp
15. 描述: XPath语言的基础教程,包含大量示例。

MDN Web Docs - XML DOM

• 链接:https://developer.mozilla.org/en-US/docs/Web/API/XML_DOM
• 描述: Mozilla开发者网络提供的XML DOM文档,包含详细的API参考和示例。

W3Schools - XML DOM Tutorial

• 链接:https://www.w3schools.com/xml/dom_intro.asp
• 描述: 提供XML DOM基础教程,适合初学者入门。

Java XML Documentation

• 链接:https://docs.oracle.com/javase/tutorial/jaxp/index.html
• 描述: Oracle官方Java XML处理教程,包括DOM、SAX和XSLT。

Python XML Processing Documentation

• 链接:https://docs.python.org/3/library/xml.dom.html
• 描述: Python官方文档中关于XML DOM处理的部分。

XPath Tutorial by W3Schools

• 链接:https://www.w3schools.com/xml/xpath_intro.asp
• 描述: XPath语言的基础教程,包含大量示例。

视频教程

1. XML Crash Course平台: YouTube链接:https://www.youtube.com/watch?v=siKLOO3bENg描述: 提供XML基础知识的快速入门视频。
2. 平台: YouTube
3. 链接:https://www.youtube.com/watch?v=siKLOO3bENg
4. 描述: 提供XML基础知识的快速入门视频。
5. XML Tutorial for Beginners平台: YouTube链接:https://www.youtube.com/watch?v=QCBjIqJ7Y7g描述: 面向初学者的XML教程,包括DOM操作。
6. 平台: YouTube
7. 链接:https://www.youtube.com/watch?v=QCBjIqJ7Y7g
8. 描述: 面向初学者的XML教程,包括DOM操作。
9. Java XML Tutorial平台: YouTube链接:https://www.youtube.com/watch?v=Z2T-j1V-5Ks描述: 使用Java处理XML的详细教程。
10. 平台: YouTube
11. 链接:https://www.youtube.com/watch?v=Z2T-j1V-5Ks
12. 描述: 使用Java处理XML的详细教程。

XML Crash Course

• 平台: YouTube
• 链接:https://www.youtube.com/watch?v=siKLOO3bENg
• 描述: 提供XML基础知识的快速入门视频。

XML Tutorial for Beginners

• 平台: YouTube
• 链接:https://www.youtube.com/watch?v=QCBjIqJ7Y7g
• 描述: 面向初学者的XML教程,包括DOM操作。

Java XML Tutorial

• 平台: YouTube
• 链接:https://www.youtube.com/watch?v=Z2T-j1V-5Ks
• 描述: 使用Java处理XML的详细教程。

工具和软件

1. XML Notepad链接:https://microsoft.github.io/XmlNotepad/描述: 微软开发的免费XML编辑器,提供直观的树形视图和编辑功能。
2. 链接:https://microsoft.github.io/XmlNotepad/
3. 描述: 微软开发的免费XML编辑器,提供直观的树形视图和编辑功能。
4. ** Oxygen XML Editor**链接:https://www.oxygenxml.com/描述: 功能强大的XML编辑器,提供XML开发、编辑和验证功能(商业软件,提供试用版)。
5. 链接:https://www.oxygenxml.com/
6. 描述: 功能强大的XML编辑器,提供XML开发、编辑和验证功能(商业软件,提供试用版)。
7. XMLSpy链接:https://www.altova.com/xmlspy描述: 专业的XML编辑器和开发环境(商业软件,提供试用版)。
8. 链接:https://www.altova.com/xmlspy
9. 描述: 专业的XML编辑器和开发环境(商业软件,提供试用版)。
10. Online XML Editor链接:https://www.freeformatter.com/xml-editor-xsd-validator.html描述: 在线XML编辑器和验证工具,无需安装即可使用。
11. 链接:https://www.freeformatter.com/xml-editor-xsd-validator.html
12. 描述: 在线XML编辑器和验证工具,无需安装即可使用。

XML Notepad

• 链接:https://microsoft.github.io/XmlNotepad/
• 描述: 微软开发的免费XML编辑器,提供直观的树形视图和编辑功能。

** Oxygen XML Editor**

• 链接:https://www.oxygenxml.com/
• 描述: 功能强大的XML编辑器,提供XML开发、编辑和验证功能(商业软件,提供试用版)。

XMLSpy

• 链接:https://www.altova.com/xmlspy
• 描述: 专业的XML编辑器和开发环境(商业软件,提供试用版)。

Online XML Editor

• 链接:https://www.freeformatter.com/xml-editor-xsd-validator.html
• 描述: 在线XML编辑器和验证工具,无需安装即可使用。

书籍推荐

1. 《XML Bible》by Elliotte Rusty Harold描述: 全面的XML参考书,涵盖XML基础、DOM、SAX、XSLT等技术。
2. 描述: 全面的XML参考书,涵盖XML基础、DOM、SAX、XSLT等技术。
3. 《Java and XML》by Brett McLaughlin描述: 专注于Java中XML处理的书籍,包含DOM、SAX、JDOM等技术的详细说明。
4. 描述: 专注于Java中XML处理的书籍,包含DOM、SAX、JDOM等技术的详细说明。
5. 《Python & XML》by Christopher Jones, Fred L. Drake Jr.描述: 介绍如何使用Python处理XML文档,包括DOM、SAX和XPath等技术。
6. 描述: 介绍如何使用Python处理XML文档,包括DOM、SAX和XPath等技术。
7. 《Learning XML》by Erik T. Ray描述: 适合初学者的XML入门书籍,讲解清晰,示例丰富。
8. 描述: 适合初学者的XML入门书籍,讲解清晰,示例丰富。

《XML Bible》by Elliotte Rusty Harold

• 描述: 全面的XML参考书,涵盖XML基础、DOM、SAX、XSLT等技术。

《Java and XML》by Brett McLaughlin

• 描述: 专注于Java中XML处理的书籍,包含DOM、SAX、JDOM等技术的详细说明。

《Python & XML》by Christopher Jones, Fred L. Drake Jr.

• 描述: 介绍如何使用Python处理XML文档,包括DOM、SAX和XPath等技术。

《Learning XML》by Erik T. Ray

• 描述: 适合初学者的XML入门书籍,讲解清晰,示例丰富。

练习项目

1. XML配置文件解析器描述: 创建一个应用程序,可以读取和解析XML配置文件,提取配置信息并使用它们。
2. 描述: 创建一个应用程序,可以读取和解析XML配置文件,提取配置信息并使用它们。
3. RSS新闻聚合器描述: 开发一个RSS新闻聚合器,从多个RSS源获取新闻,使用XML DOM解析和显示新闻内容。
4. 描述: 开发一个RSS新闻聚合器,从多个RSS源获取新闻,使用XML DOM解析和显示新闻内容。
5. XML数据转换工具描述: 创建一个工具,可以将XML数据转换为其他格式(如JSON、CSV等),或反之。
6. 描述: 创建一个工具,可以将XML数据转换为其他格式(如JSON、CSV等),或反之。
7. XML验证器描述: 开发一个XML验证工具,可以检查XML文档是否符合指定的DTD或XSD模式。
8. 描述: 开发一个XML验证工具,可以检查XML文档是否符合指定的DTD或XSD模式。

XML配置文件解析器

• 描述: 创建一个应用程序,可以读取和解析XML配置文件,提取配置信息并使用它们。

RSS新闻聚合器

• 描述: 开发一个RSS新闻聚合器,从多个RSS源获取新闻,使用XML DOM解析和显示新闻内容。

XML数据转换工具

• 描述: 创建一个工具,可以将XML数据转换为其他格式(如JSON、CSV等),或反之。

XML验证器

• 描述: 开发一个XML验证工具,可以检查XML文档是否符合指定的DTD或XSD模式。

总结

XML DOM是一种强大的工具,它允许开发者以编程方式操作XML文档。本指南从基础入门到高级应用,全面解析了XML文档对象模型的使用方法和技巧。

我们首先介绍了XML DOM的基本概念和结构,然后详细讲解了如何在不同编程语言(JavaScript、Python和Java)中加载、解析和遍历XML文档。接着,我们深入探讨了节点操作、属性处理、高级查询(XPath和XSLT)以及错误处理等方面的内容。

为了提高性能,我们介绍了使用SAX解析器处理大型XML文件、使用XPath进行高效查询以及缓存XPath表达式等优化技巧。此外,我们还通过实际应用案例(XML配置文件处理、RSS新闻阅读器和XML数据导出导入)展示了XML DOM在实际项目中的应用。

最后,我们提供了丰富的学习资源,包括在线教程、视频教程、工具软件、推荐书籍和练习项目,帮助读者进一步深入学习和实践XML DOM编程。

无论您是初学者还是有经验的开发者,掌握XML DOM编程技巧都将为您的开发工作带来很大的便利。希望本指南能够帮助您全面了解和应用XML DOM,为您的项目开发提供有力支持。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则