24

ファイルとしてローカルに保存されている DTD に対して XML ファイルを検証するにはどうすればよいですか? XML ファイルに DOCTYPE 宣言がありません (またはオーバーライドする必要がある宣言がある可能性があります)。私はこのスレッドを見ましたが、彼らが.NETを使用しているという事実に加えて、これが良い解決策であるとは思えません.

ご意見をお待ちしております。

4

3 に答える 3

26

理想的な世界では、 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 からスキーマ インスタンスを作成するためのサポートが含まれていません。サードパーティの実装を追跡できる場合があります。

最善の策は、他のメカニズムを使用して解析する前に、ドキュメントを変更して 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 スキーマを使用して検証する方がはるかに簡単です。

于 2009-07-08T10:50:48.763 に答える
3

前述のものがうまくいくと確信しています..

ご協力ありがとうございます。DOCTYPE がまったく指定されていない場合はどうなるでしょうか。その場合、EntityResolver は役に立ちませんよね?— サイモン 09 年 7 月 8 日 6:34

@Bluegene: DOCTYPE がない場合、何に対して検証していますか? — J-16 SDiZ 09 年 7 月 8 日 7:12 に

私自身のDTDに対して。受信した XML が、送信者が指定した DTD だけでなく、自分の DTD に準拠していることを確認したいだけです。— サイモン 09 年 7 月 8 日 23:09

問題が、作成者ではなく dtd に対して検証することである場合は、doctype の詳細と xml ファイルに何が含まれている必要があるかを示す明確なドキュメントがあることを確認する必要があります。

于 2012-10-20T09:00:18.070 に答える
1

を実装する必要があります。この例EntityResolverを確認してください。

于 2009-07-08T06:24:02.717 に答える