WD1X.COM - 问答一下,轻松解决,电脑应用解决专家
主板显卡CPU内存显示器
硬盘维修显卡维修显示器维修
注册表系统命令DOS命令Win8
存储光存储鼠标键盘
内存维修打印机维修
WinXPWin7Win11Linux
硬件综合机箱电源散热器手机数码
主板维修CPU维修键盘鼠标维修
Word教程Excel教程PowerPointWPS
网络工具系统工具图像工具
数据库javascript服务器
PHP教程CSS教程XML教程

用SAX和XNI检测XML文档的编码(2)

更新时间:2009-06-21 11:17 作者:佚名点击:

  该方法花费 90% 的时间,有可能会更多一点。但是,SAX 解析器不需要支持 Locator 接口,更不用说 Locator2 以及其他的接口。如果知道正在使用的是 Xerces,第二种方法是使用 XNI。

  Xerces Native Interface

  使用 XNI 的方法与 SAX 是非常相似的(实际上,在 Xerces 中,SAX 解析器是本机 XNI 解析器之上很薄的一层)。总之,这种方法更容易一些,因为编码作为参数直接传递给 startDocument()。您只需要读取它,如清单 2 所示。

  清单 2. 使用 XNI 确定文档的编码

import java.io.IOException;
import org.apache.xerces.parsers.*;
import org.apache.xerces.xni.*;
import org.apache.xerces.xni.parser.*;
public class XNIEncodingDetector extends XMLDocumentParser {
  
  public static void main(String[] args) throws XNIException, IOException {
    XNIEncodingDetector parser = new XNIEncodingDetector();
    for (int i = 0; i < args.length; i++) {
      try {
        XMLInputSource document = new XMLInputSource("", args[i], "");
        parser.parse(document);
      }
      catch (XNIException ex) {
        System.out.println(parser.encoding);
      }
    }
  }
  
  private String encoding = "unknown";
  @Override
  public void startDocument(XMLLocator locator, String encoding,
    NamespaceContext context, Augmentations augs)
        throws XNIException {
    this.encoding = encoding;
    throw new XNIException("Early termination");
  }
}

请注意,因为一些未知的原因,该技术只使用 org.apache.xerces 中实际的 Xerces 类,而不使用与 Sun 的 JDK 6 绑定的 com.sun.org.apache.xerces.internal 中重新打包的 Xerces 类。

  XNI 提供了另外一个 SAX 不具有的功能。在少数情况下,在 XML 声明中声明的编码不是实际的编码。SAX 只报告实际编码,但是,XNI 也可以告诉您在 xmlDecl() 方法中声明的编码,如清单 3 所示。

  清单 3. 使用 XNI 确定文档的声明的编码和实际的编码

import java.io.IOException;
import org.apache.xerces.parsers.*;
import org.apache.xerces.xni.*;
import org.apache.xerces.xni.parser.*;
public class AdvancedXNIEncodingDetector extends XMLDocumentParser {
  
  public static void main(String[] args) throws XNIException, IOException {
    AdvancedXNIEncodingDetector parser = new AdvancedXNIEncodingDetector();
    for (int i = 0; i < args.length; i++) {
      try {
        XMLInputSource document = new XMLInputSource("", args[i], "");
        parser.parse(document);
      }
      catch (XNIException ex) {
        System.out.println("Actual: " + parser.actualEncoding);
        System.out.println("Declared: " + parser.declaredEncoding);
      }
    }
  }
  
  private String actualEncoding = "unknown";
  private String declaredEncoding = "none";
  @Override
  public void startDocument(XMLLocator locator, String encoding,
    NamespaceContext namespaceContext, Augmentations augs)
        throws XNIException {
    this.actualEncoding = encoding;
    this.declaredEncoding = "none"; // reset
  }
  @Override
  // this method is not called if there's no XML declaration
  public void xmlDecl(String version, String encoding,
   String standalone, Augmentations augs) throws XNIException {
    this.declaredEncoding = encoding;
  }
  @Override
  public void startElement(QName element, XMLAttributes attributes,
   Augmentations augs) throws XNIException {
     throw new XNIException("Early termination");
  }
  
}

  通常情况下,如果声明的编码和实际的编码不同,就表明服务器存在一个 bug。最常见的原因是由于 HTTP Content-type 报头指定的编码与在 XML 声明中声明的编码不同。在本例中,要严格遵守规范,要求优先考虑 HTTP 报头的值。但实际上,很可能 XML 声明中的值是正确的。

  结束语

  通常情况下,您不需要了解输入文档的编码。只需要用解析器处理输入文档,以 UTF-8 编码输出结果即可。但是,有些情况下需要知道输入编码,SAX 和 XNI 可以提供快速而有效的方法来解决这一问题。

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
你可能感兴趣的内容