【问题标题】:Using an XML Catalog with a Java library that uses JAXP internally将 XML 目录与内部使用 JAXP 的 Java 库一起使用
【发布时间】:2011-03-05 07:24:16
【问题描述】:

我正在使用 Apache Web 服务 xml rpc 库向 rpc 服务发出请求。在该过程中的某处是一个 xml 文档,其中包含对 http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd 的 DTD 引用,该库在解析 XML 时尝试下载该文档。该下载失败并显示 503 状态代码,因为 w3c 正在阻止从 Java 客户端重复下载这个基本上是静态的文档。

解决方案是使用 XML 目录在本地缓存 DTD。但是,虽然我可以找到直接在 JAXP SAXParser 实例上设置 EntityHandler 以启用目录解析器支持的示例,但我实际上无法访问此处的底层解析器。它只是被 xml rpc 库使用。有什么方法可以设置全局属性或告诉 JAXP 使用 XML 目录的东西吗?

【问题讨论】:

    标签: java xml catalog


    【解决方案1】:

    我想你想要系统属性xml.catalog.files

    看看http://xml.apache.org/commons/components/resolver/resolver-article.html

    顺便说一句,这是在 Google 搜索 jaxp catalog 时的第三次点击

    【讨论】:

    • 我看过那篇文章,并且已经尝试将 xml-resolver 集成到我的项目中。问题是 xml.catalog.files 系统属性只有在您将 XML Resolver 安装为您的 JAXP 阅读器实例上的实体解析器后才会生效。我的问题是我无法访问 Web 服务库内部使用的 JAXP 阅读器实例。
    • 如果在启动程序时在命令行中设置了该属性,解析器工厂不会“看到”它吗?
    【解决方案2】:

    不幸的是,设置 xml.catalog.files 对解析器工厂没有任何影响。理想情况下当然应该这样做,但使用解析器的唯一方法是以某种方式添加一个方法,该方法将解析委托给 SAX 解析器使用的处理程序中的目录解析器。

    如果您已经在使用 SAX 解析器,那非常简单:

     final CatalogResolver catalogResolver = new CatalogResolver();
      DefaultHandler handler = new DefaultHandler() {
            public InputSource resolveEntity (String publicId, String systemId) {
                return catalogResolver.resolveEntity(publicId, systemId);
            }
            public void startElement(String namespaceURI, String lname, String qname,
               Attributes attrs) { 
               // the stuff you'd normally do
            }
            ...
         };
    
      SAXParserFactory factory = SAXParserFactory.newInstance();
      factory.setNamespaceAware(true);
      SAXParser saxParser = factory.newSAXParser();
      String url = args.length == 0 ? "http://horstmann.com/index.html" : args[0];
      saxParser.parse(new URL(url).openStream(), handler);
    

    否则,您需要确定是否可以提供自己的实体解析器。使用 javax.xml.parsers.DocumentBuilder,您可以。使用 scala.xml.XML 对象,你不能,但你可以使用诡计:

    val res = new com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver
    
    val loader = new factory.XMLLoader[Elem] {
      override def adapter = new parsing.NoBindingFactoryAdapter() {
        override def resolveEntity(publicId: String, systemId: String) = {
          res.resolveEntity(publicId, systemId) 
        }
      }
    }
    
    val doc = loader.load(new URL("http://horstmann.com/index.html"))enter code here
    

    【讨论】:

      猜你喜欢
      • 2010-09-05
      • 1970-01-01
      • 2012-01-09
      • 2016-07-13
      • 2014-10-31
      • 2014-04-26
      • 2021-06-06
      • 1970-01-01
      相关资源
      最近更新 更多