| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- unit XMLParse;
- { XML parser. Currently just calls MSXML 6.0 to do the real work. }
- interface
- uses
- Windows, SysUtils, Variants;
- type
- IXMLNode = interface
- function GetAttribute(const AName: String): String;
- function GetOptionalAttribute(const AName: String): String;
- function GetFirstChild: IXMLNode;
- function GetNodeName: String;
- function GetNextSibling: IXMLNode;
- function GetNodeType: Integer;
- function GetParentNode: IXMLNode;
- function GetPreviousSibling: IXMLNode;
- function GetRealMSXMLNode: OleVariant;
- function GetText: String;
- function HasAttribute(const AName: String): Boolean;
- function TransformNode(const Stylesheet: IXMLNode): String;
- property Attributes[const AName: String]: String read GetAttribute;
- property OptionalAttributes[const AName: String]: String read GetOptionalAttribute;
- property FirstChild: IXMLNode read GetFirstChild;
- property NextSibling: IXMLNode read GetNextSibling;
- property NodeName: String read GetNodeName;
- property NodeType: Integer read GetNodeType;
- property ParentNode: IXMLNode read GetParentNode;
- property PreviousSibling: IXMLNode read GetPreviousSibling;
- property Text: String read GetText;
- end;
- TXMLDocument = class
- private
- FDoc: OleVariant;
- function GetRoot: IXMLNode;
- public
- constructor Create;
- procedure LoadFromFile(const AFilename: String);
- procedure StripComments;
- property Root: IXMLNode read GetRoot;
- end;
- const
- { Values for the NodeType property }
- NODE_INVALID = 0;
- NODE_ELEMENT = 1;
- NODE_ATTRIBUTE = 2;
- NODE_TEXT = 3;
- NODE_CDATA_SECTION = 4;
- NODE_ENTITY_REFERENCE = 5;
- NODE_ENTITY = 6;
- NODE_PROCESSING_INSTRUCTION = 7;
- NODE_COMMENT = 8;
- NODE_DOCUMENT = 9;
- NODE_DOCUMENT_TYPE = 10;
- NODE_DOCUMENT_FRAGMENT = 11;
- NODE_NOTATION = 12;
- implementation
- uses
- ActiveX, ComObj;
- type
- TXMLNode = class(TInterfacedObject, IXMLNode)
- private
- FRealNode: OleVariant;
- function GetFirstChild: IXMLNode;
- function GetAttribute(const AName: String): String;
- function GetOptionalAttribute(const AName: String): String;
- function GetNextSibling: IXMLNode;
- function GetNodeName: String;
- function GetNodeType: Integer;
- function GetParentNode: IXMLNode;
- function GetPreviousSibling: IXMLNode;
- function GetRealMSXMLNode: OleVariant;
- function GetText: String;
- function HasAttribute(const AName: String): Boolean;
- function TransformNode(const Stylesheet: IXMLNode): String;
- public
- constructor Create(const ARealNode: OleVariant);
- end;
- function IsVarAssigned(const AVariant: OleVariant): Boolean;
- begin
- case VarType(AVariant) of
- varEmpty: Result := False;
- varDispatch: Result := Assigned(TVarData(AVariant).VDispatch);
- else
- raise Exception.Create('IsVarAssigned: Unexpected variant type');
- end;
- end;
- function MakeNode(const ARealNode: OleVariant): IXMLNode;
- begin
- if IsVarAssigned(ARealNode) then
- Result := TXMLNode.Create(ARealNode)
- else
- Result := nil;
- end;
- function VariantToString(const V: OleVariant): String;
- begin
- if VarType(V) <> varOleStr then
- raise Exception.Create('VariantToUTF8String: Expected varOleStr');
- Result := TVarData(V).VOleStr;
- end;
- { TXMLDocument }
- constructor TXMLDocument.Create;
- begin
- inherited Create;
- FDoc := CreateOleObject('MSXML2.DOMDocument.6.0');
- FDoc.setProperty('ProhibitDTD', False);
- FDoc.resolveExternals := True;
- FDoc.async := False;
- FDoc.preserveWhitespace := True;
- end;
- function TXMLDocument.GetRoot: IXMLNode;
- begin
- Result := MakeNode(FDoc.documentElement);
- end;
- procedure TXMLDocument.LoadFromFile(const AFilename: String);
- begin
- if not FDoc.load(AFilename) then begin
- if Integer(FDoc.parseError.line) <> 0 then
- raise Exception.CreateFmt('XML parse error (line %d, column %d): %s',
- [Integer(FDoc.parseError.line), Integer(FDoc.parseError.linepos),
- FDoc.parseError.reason])
- else
- raise Exception.CreateFmt('XML parse error: %s', [FDoc.parseError.reason]);
- end;
- end;
- procedure TXMLDocument.StripComments;
- begin
- FDoc.selectNodes('//comment()').removeAll;
- end;
- { TXMLNode }
- constructor TXMLNode.Create(const ARealNode: OleVariant);
- begin
- inherited Create;
- FRealNode := ARealNode;
- end;
- function TXMLNode.GetAttribute(const AName: String): String;
- var
- N: OleVariant;
- begin
- N := FRealNode.attributes.getNamedItem(AName);
- if not IsVarAssigned(N) then
- raise Exception.CreateFmt('Attribute "%s" does not exist', [AName]);
- Result := VariantToString(N.value);
- end;
- function TXMLNode.GetOptionalAttribute(const AName: String): String;
- var
- N: OleVariant;
- begin
- N := FRealNode.attributes.getNamedItem(AName);
- if not IsVarAssigned(N) then
- Result := ''
- else
- Result := VariantToString(N.value);
- end;
- function TXMLNode.GetFirstChild: IXMLNode;
- begin
- Result := MakeNode(FRealNode.firstChild);
- end;
- function TXMLNode.GetNodeName: String;
- begin
- Result := VariantToString(FRealNode.nodeName);
- end;
- function TXMLNode.GetNextSibling: IXMLNode;
- begin
- Result := MakeNode(FRealNode.nextSibling);
- end;
- function TXMLNode.GetNodeType: Integer;
- begin
- Result := FRealNode.nodeType;
- end;
- function TXMLNode.GetParentNode: IXMLNode;
- begin
- Result := MakeNode(FRealNode.parentNode);
- end;
- function TXMLNode.GetPreviousSibling: IXMLNode;
- begin
- Result := MakeNode(FRealNode.previousSibling);
- end;
- function TXMLNode.GetRealMSXMLNode: OleVariant;
- begin
- Result := FRealNode;
- end;
- function TXMLNode.GetText: String;
- begin
- Result := VariantToString(FRealNode.text);
- end;
- function TXMLNode.HasAttribute(const AName: String): Boolean;
- begin
- Result := IsVarAssigned(FRealNode.attributes.getNamedItem(AName));
- end;
- function TXMLNode.TransformNode(const Stylesheet: IXMLNode): String;
- begin
- Result := VariantToString(FRealNode.transformNode(Stylesheet.GetRealMSXMLNode));
- end;
- end.
|