簡體   English   中英

使用Java驗證針對本地DTD文件的XML文件

[英]Validate an XML file against local DTD file with Java

如何根據本地存儲為文件的DTD驗證XML文件? XML文件沒有任何DOCTYPE聲明(或者可能有一個應該被覆蓋的聲明)。 我看了一下這個帖子,但除了他們使用.NET之外,我懷疑這是一個很好的解決方案。

任何輸入贊賞!

在理想的世界中,您可以使用Validator進行驗證 像這樣的東西:

SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.XML_DTD_NS_URI);
Schema schema = schemaFactory.newSchema(new File(
    "xmlValidate.dtd"));
Validator validator = schema.newValidator();
validator.validate(new StreamSource("xmlValidate.xml"));

不幸的是,Sun實現(至少從Java 6開始)不包括從DTD創建Schema實例的支持。 您可以跟蹤第三方實施。

您最好的選擇可能是在使用其他機制解析之前更改文檔以包含DTD。


您可以使用轉換器插入DTD聲明:

TransformerFactory tf = TransformerFactory
    .newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(
    OutputKeys.DOCTYPE_SYSTEM, "xmlValidate.dtd");
transformer.transform(new StreamSource(
    "xmlValidate.xml"), new StreamResult(System.out));

......但這似乎並沒有取代現有的DTD聲明。


這個StAX事件閱讀器可以完成這項工作:

  public static class DTDReplacer extends
      EventReaderDelegate {

    private final XMLEvent dtd;
    private boolean sendDtd = false;

    public DTDReplacer(XMLEventReader reader, XMLEvent dtd) {
      super(reader);
      if (dtd.getEventType() != XMLEvent.DTD) {
        throw new IllegalArgumentException("" + dtd);
      }
      this.dtd = dtd;
    }

    @Override
    public XMLEvent nextEvent() throws XMLStreamException {
      if (sendDtd) {
        sendDtd = false;
        return dtd;
      }
      XMLEvent evt = super.nextEvent();
      if (evt.getEventType() == XMLEvent.START_DOCUMENT) {
        sendDtd = true;
      } else if (evt.getEventType() == XMLEvent.DTD) {
        // discard old DTD
        return super.nextEvent();
      }
      return evt;
    }

  }

它將在文檔開始后立即發送給定的DTD聲明,並從舊文檔中丟棄任何聲明。

演示用法:

XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent dtd = eventFactory
    .createDTD("<!DOCTYPE Employee SYSTEM \"xmlValidate.dtd\">");

XMLInputFactory inFactory = XMLInputFactory.newInstance();
XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
XMLEventReader reader = inFactory
    .createXMLEventReader(new StreamSource(
        "xmlValidate.xml"));
reader = new DTDReplacer(reader, dtd);
XMLEventWriter writer = outFactory.createXMLEventWriter(System.out);
writer.add(reader);
writer.flush();

// TODO error and proper stream handling

請注意,XMLEventReader可以構成執行驗證的其他轉換機制的源。


如果您有這個選項,使用W3架構驗證會容易得多。

我很確定前面提到的東西會起作用..

感謝您的幫助,但如果沒有指定DOCTYPE怎么辦? 在這種情況下,EntityResolver不會幫助我,不是嗎? - 西蒙2009年7月8日6:34

@Bluegene:如果沒有DOCTYPE,你有什么效果? - J-16 SDiZ 2009年7月8日7:12

反對我自己的DTD。 我只是想確保我收到的XML符合我的DTD,而不僅僅是發件人指定的任何DTD。 - 西蒙2009年7月8日23:09

如果問題是您希望對您的dtd而不是作者進行驗證,則應確保有明確的文檔詳細說明doctype以及xml文件中必須包含的內容

您必須實現EntityResolver ,請查看此示例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM