如何使用Delphi检查XML文件是否格式正确?

8

如何检查XML文件是否格式良好,没有无效的字符或标签?

例如,考虑以下XML:

<?xml version="1.0"?>
<PARTS>
   <TITLE>Computer Parts</TITLE>
   <PART>
      <ITEM>Motherboard</ITEM>
      <MANUFACTURER>ASUS</MANUFACTURER>
      <MODEL>P3B-F</MODEL>
      <COST> 123.00</COST>
   </PART>
   <PART>
      <ITEM>Video Card</ITEM>
      <MANUFACTURER>ATI</MANUFACTURER>
      <MODEL>All-in-Wonder Pro</MODEL>
      <COST> 160.00</COST>
   </PART>
</PARTSx>

最后一个标签</PARTSx>必须是</PARTS>

4
您的标题提到了验证,但正文似乎只是关于格式正确的XML。这是两个不同的事情。没有DTD或XSD,您无法验证 XML。您确定知道自己在要求什么吗? - Rob Kennedy
同意Rob的观点,你需要先了解格式良好的XML,然后再去学习有效的XML(你需要一个XML模式)。任何XML解析器都可以检查格式是否良好。 - Jeroen Wiert Pluimers
2个回答

13

您可以使用由MSXML DOMDocument返回的IXMLDOMParseError接口。

该接口返回一系列属性,帮助您识别问题。

  • errorCode 包含最后一个解析错误的错误代码。只读。
  • filepos 包含发生错误的绝对文件位置。只读。
  • line 指定包含错误的行号。只读。
  • linepos 包含发生错误的行内字符位置。
  • reason 描述错误原因。只读。
  • srcText 返回包含错误的行的完整文本。只读。
  • url 包含最后一个错误的 XML 文档的 URL。只读。

请检查这两个使用 MSXML 6.0 的函数(您也可以使用其他版本)。

uses
  Variants,
  Comobj,
  SysUtils;

function IsValidXML(const XmlStr :string;var ErrorMsg:string) : Boolean;
var
  XmlDoc : OleVariant;
begin
  XmlDoc := CreateOleObject('Msxml2.DOMDocument.6.0');
  try
    XmlDoc.Async := False;
    XmlDoc.validateOnParse := True;
    Result:=(XmlDoc.LoadXML(XmlStr)) and (XmlDoc.parseError.errorCode = 0);
    if not Result then
     ErrorMsg:=Format('Error Code : %s  Msg : %s line : %s Character  Position : %s Pos in file : %s',
     [XmlDoc.parseError.errorCode,XmlDoc.parseError.reason,XmlDoc.parseError.Line,XmlDoc.parseError.linepos,XmlDoc.parseError.filepos]);
  finally
    XmlDoc:=Unassigned;
  end;
end;

function IsValidXMLFile(const XmlFile :TFileName;var ErrorMsg:string) : Boolean;
var
  XmlDoc : OleVariant;
begin
  XmlDoc := CreateOleObject('Msxml2.DOMDocument.6.0');
  try
    XmlDoc.Async := False;
    XmlDoc.validateOnParse := True;
    Result:=(XmlDoc.Load(XmlFile)) and (XmlDoc.parseError.errorCode = 0);
    if not Result then
     ErrorMsg:=Format('Error Code : %s  Msg : %s line : %s Character  Position : %s Pos in file : %s',
     [XmlDoc.parseError.errorCode,XmlDoc.parseError.reason,XmlDoc.parseError.Line,XmlDoc.parseError.linepos,XmlDoc.parseError.filepos]);
  finally
    XmlDoc:=Unassigned;
  end;
end;

5
您是如何创建/接收XML的?任何明智的解析器都会捕获此类问题。
例如,使用OmniXML
uses
  OmniXML;

type
  TForm1=class(TForm)
    Memo1: TMemo;
    //...
  private
    FXMLDoc: IXMLDocument;
    procedure FormCreate(Sender: TObject);
    procedure CheckXML;
  end;

implementation

uses
  OmniXMLUtils;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Load your sample XML. Can also do Memo1.Text := YourXML
  Memo1.Lines.LoadFromFile('YourXMLFile.xml');
end;

procedure TForm1.CheckXML;
begin
  FXMLDoc := CreateXMLDoc;
  // The next line raises an exception with your sample file.
  XMLLoadFromAnsiString(FXMLDoc, Memo1.Text); 
end;

Ken,我正在处理许多由外部应用程序生成的XML文件,有时它们会包含无效字符或未终止的标记。 - Salvador
2
@Salvador:一旦接收到它们,您是如何处理它们的?正如我所说,任何体面的解析器都会针对格式不正确或无效的文件引发异常;如果您正在使用自己的代码进行解析,则不应该这样做。 :) - Ken White

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接