XML处理:命名空间、SAX解析与文档生成
立即解锁
发布时间: 2025-08-18 00:08:32 阅读量: 2 订阅数: 9 

# XML 处理:命名空间、SAX 解析与文档生成
## 1. XML 命名空间机制
### 1.1 命名空间的概念
在 Java 中,我们使用包来避免类名冲突,只要不同类不在同一个包中,就可以使用相同的名称。XML 也有类似的命名空间机制,用于处理元素和属性名称的冲突。命名空间由统一资源标识符(URI)标识,常见的是 HTTP URL 形式,例如 `http://www.w3.org/2001/XMLSchema`。需要注意的是,这里的 URL 仅作为标识符字符串,并不用于定位文档。
### 1.2 命名空间的唯一性
使用 HTTP URL 作为命名空间标识符的原因是容易确保其唯一性。如果选择一个真实的 URL,域名系统会保证主机部分的唯一性,组织可以安排 URL 其余部分的唯一性,这与 Java 包名中使用反向域名的原理相同。
### 1.3 命名空间的使用方式
#### 1.3.1 简单命名空间使用
在 XML 中,可以通过 `xmlns` 属性指定命名空间,示例如下:
```xml
<element xmlns="namespace URI">
children
</element>
```
此时,该元素及其子元素都属于指定的命名空间。子元素也可以提供自己的命名空间,例如:
```xml
<element xmlns="namespace URI">
<child xmlns="namespace URI #2">
grandchildren
</child>
more children
</element>
```
这样,第一个子元素和孙元素就属于第二个命名空间。
#### 1.3.2 命名空间别名
当需要处理多个命名空间或命名空间嵌套时,可以使用命名空间别名。示例如下:
```xml
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
...
</xsl:stylesheet>
```
`xmlns:alias="namespace URI"` 定义了命名空间和别名,这里的别名是 `xsl`,`xsl:stylesheet` 表示 `http://www.w3.org/1999/XSL/Transform` 命名空间中的 `stylesheet`。
### 1.4 解析器对命名空间的处理
默认情况下,Sun DOM 解析器不支持命名空间感知。要开启命名空间处理,需要调用 `DocumentBuilderFactory` 的 `setNamespaceAware` 方法:
```java
factory.setNamespaceAware(true);
```
开启后,解析器生成的所有构建器都支持命名空间,每个节点有三个属性:
- 限定名(Qualified name):带有别名前缀,通过 `getNodeName`、`getTagName` 等方法返回。
- 本地名(Local name):不带前缀或命名空间,通过 `getLocalName` 方法返回。
- 命名空间 URI(Namespace URI):通过 `getNamespaceURI` 方法返回。
示例如下:
```xml
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
```
解析器会报告:
- 限定名 = `xsl:stylesheet`
- 本地名 = `stylesheet`
- 命名空间 URI = `http://www.w3.org/1999/XSL/Transform`
### 1.5 相关 API 方法
| 类 | 方法 | 描述 |
| ---- | ---- | ---- |
| `org.w3c.dom.Node` | `String getLocalName()` | 返回本地名(无别名前缀),若解析器不支持命名空间感知则返回 `null` |
| `org.w3c.dom.Node` | `String getNameSpaceURI()` | 返回命名空间 URI,若节点不属于命名空间或解析器不支持命名空间感知则返回 `null` |
| `javax.xml.parsers.DocumentBuilderFactory` | `boolean isNamespaceAware()` | 判断工厂的 `namespaceAware` 属性 |
| `javax.xml.parsers.DocumentBuilderFactory` | `void setNamespaceAware(boolean value)` | 设置工厂的 `namespaceAware` 属性,若为 `true`,生成的解析器支持命名空间感知 |
## 2. 使用 SAX 解析器
### 2.1 SAX 解析器的适用场景
DOM 解析器会将整个 XML 文档读入树状数据结构,对于大多数实际应用来说,DOM 解析器工作良好。但当文档较大且处理算法简单,能够“即时”分析节点而无需查看整个树结构时,使用 SAX 解析器更高效。
### 2.2 SAX 解析器的工作原理
SAX 解析器在解析 XML 输入的组件时会报告事件,但不会以任何方式存储文档,是否构建数据结构取决于事件处理程序。实际上,DOM 解析器是基于 SAX 解析器构建的,它在接收解析器事件时构建 DOM 树。
### 2.3 事件处理程序
使用 SAX 解析器时,需要一个处理程序来定义各种解析事件的操作。`ContentHandler` 接口定义了几个回调方法,解析器在解析文档时会执行这些方法,最重要的方法如下:
- `startElement/endElement`:遇到开始标签或结束标签时调用。
- `characters`:遇到字符数据时调用。
- `startDocument/endDocument`:在文档开始和结束时各调用一次。
### 2.4 示例解析过程
解析以下 XML 片段:
```xml
<font>
<name>Helvetica</name>
<size units="pt">36</size>
</font>
```
解析器会生成以下调用:
1. `startElement`,元素名:`font`
2. `startElement`,元素名:`name`
3. `characters`,内容:`Helvetica`
4. `endElement`,元素名:`name`
5. `startElement`,元素名:`size`,属性:`units="pt"`
6. `characters`,内容:`36`
7. `endElement`,元素名:`size`
8. `endElement`,元素名:`font`
### 2.5 获取 SAX 解析器
获取 SAX 解析器的步骤如下:
```java
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
```
处理文档的代码如下:
```java
parser.parse(source, handler);
```
其中,`source` 可以是文件、URL 字符串或输入流,`handler` 是 `DefaultHandler` 的子类。
### 2.6 示例程序
以下是一个示例程序,用于打印 XHTML 网页中的所有超链接:
```java
import java.io.*;
import java.net.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class SAXTest {
public static void main(String[] args) throws Exception {
String url;
if (args.length == 0) {
url = "http://www.w3c.org";
System.out.println("Using " + url);
} else {
url = args[0];
}
DefaultHandler handler = new DefaultHandler() {
public void startElement(String namespaceURI, String lname, String qname, Attributes attrs) throws SAXException {
if (lname.equalsIgnoreCase("a") && attrs != null) {
for (int i = 0; i < attrs.getLength(); i++) {
String aname = attrs.getLocalName(i);
if (aname.equalsIgnoreCase("href")) {
System.out.println(attrs.getValue(i));
}
}
}
}
};
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
SAXParser saxParser = factory.newSAXParser();
InputStream in = new URL(url).openStream();
saxParser.parse(in, handler);
}
}
```
### 2.7 相关 API 方法
| 类 | 方法 | 描述 |
| ---- | ---- | ---- |
| `javax.xml.pars
0
0
复制全文
相关推荐










