2010-11-06 22:16:58 +02:00
|
|
|
unit SimpleXML;
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
Windows, SysUtils, Classes;
|
|
|
|
|
|
|
|
const
|
|
|
|
BINXML_USE_WIDE_CHARS = 1;
|
|
|
|
|
|
|
|
XSTR_NULL = '{{null}}';
|
2013-05-31 16:03:11 +06:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
NODE_INVALID = $00000000;
|
|
|
|
NODE_ELEMENT = $00000001;
|
|
|
|
NODE_ATTRIBUTE = $00000002;
|
|
|
|
NODE_TEXT = $00000003;
|
|
|
|
NODE_CDATA_SECTION = $00000004;
|
|
|
|
NODE_ENTITY_REFERENCE = $00000005;
|
|
|
|
NODE_ENTITY = $00000006;
|
|
|
|
NODE_PROCESSING_INSTRUCTION = $00000007;
|
|
|
|
NODE_COMMENT = $00000008;
|
|
|
|
NODE_DOCUMENT = $00000009;
|
|
|
|
NODE_DOCUMENT_TYPE = $0000000A;
|
|
|
|
NODE_DOCUMENT_FRAGMENT = $0000000B;
|
|
|
|
NODE_NOTATION = $0000000C;
|
|
|
|
|
|
|
|
type
|
|
|
|
IXmlDocument = interface;
|
|
|
|
IXmlElement = interface;
|
|
|
|
IXmlText = interface;
|
|
|
|
IXmlCDATASection = interface;
|
|
|
|
IXmlComment = interface;
|
|
|
|
IXmlProcessingInstruction = interface;
|
|
|
|
|
|
|
|
|
|
|
|
// IXmlBase - ������� ��������� ��� ���� ����������� SimpleXML.
|
|
|
|
IXmlBase = interface
|
|
|
|
// GetObject - ���������� ������ �� ������, ����������� ���������.
|
|
|
|
function GetObject: TObject;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// IXmlNameTable - ������� ����. ������� ����� �������������� �����
|
|
|
|
// ���������� �������� �������������. ������������ ��� ��������
|
|
|
|
// �������� ����� � ���������.
|
|
|
|
IXmlNameTable = interface(IXmlBase)
|
|
|
|
// GetID - ���������� �������� ������������� ��������� ������.
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetID(const aName: String): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
// GetID - ���������� ������, ��������������� ���������� ���������
|
|
|
|
// ��������������.
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetName(anID: Integer): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
IXmlNode = interface;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
TXmlCompareNodes = function(const aNode1, aNode2: IXmlNode): Integer;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
// IXmlNodeList - ������ �����. ������ ����������� � ���� �������.
|
|
|
|
// ������ � ��������� ������ �� �������
|
|
|
|
IXmlNodeList = interface(IXmlBase)
|
|
|
|
// Get_Count - ���������� ����� � ������
|
|
|
|
function Get_Count: Integer;
|
|
|
|
// Get_Item - �������� ���� �� �������
|
|
|
|
function Get_Item(anIndex: Integer): IXmlNode;
|
|
|
|
// Get_XML - ���������� ������������� ��������� ������ � ������� XML
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_XML: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure SortElements(aCompare: TXmlCompareNodes);
|
|
|
|
function IndexOf(const aNode: IXmlNode): Integer;
|
|
|
|
procedure Add(const aNode: IXmlNode);
|
|
|
|
procedure Insert(const aNode: IXmlNode; anIndex: Integer);
|
|
|
|
function Remove(const aNode: IXmlNode): Integer;
|
|
|
|
procedure Delete(anIndex: Integer);
|
|
|
|
procedure Clear;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
property Count: Integer read Get_Count;
|
|
|
|
property Item[anIndex: Integer]: IXmlNode read Get_Item; default;
|
2013-05-31 16:03:11 +06:00
|
|
|
property XML: String read Get_XML;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
// IXmlNode - ���� XML-������
|
|
|
|
IXmlNode = interface(IXmlBase)
|
2010-11-06 22:21:34 +02:00
|
|
|
function Get_SourceLine: Integer;
|
|
|
|
function Get_SourceCol: Integer;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
// Get_NameTable - ������� ����, ������������ ������ �����
|
|
|
|
function Get_NameTable: IXmlNameTable;
|
|
|
|
// Get_NodeName - ���������� �������� ����. ������������� �������� ����
|
|
|
|
// ������� �� ��� ����
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_NodeName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
// Get_NodeNameID - ���������� ��� �������� ����
|
|
|
|
function Get_NodeNameID: Integer;
|
|
|
|
// Get_NodeType - ���������� ��� ����
|
|
|
|
function Get_NodeType: Integer;
|
|
|
|
// Get_Text - ���������� ����� ����
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Text: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
// Set_Text - �������� ����� ����
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure Set_Text(const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
// Get_DataType - ���������� ��� ������ ���� � �������� ���������
|
|
|
|
function Get_DataType: Integer;
|
|
|
|
// Get_TypedValue - ����������
|
|
|
|
function Get_TypedValue: Variant;
|
|
|
|
// Set_TypedValue - �������� ����� ���� �� �������������� ��������
|
|
|
|
procedure Set_TypedValue(const aValue: Variant);
|
|
|
|
// Get_XML - ���������� ������������� ���� � ���� ��������� �����
|
|
|
|
// � ������� XML.
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_XML: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// CloneNode - ������� ������ ����� ������� ����
|
|
|
|
// ���� ����� ������� aDeep, �� ��������� �����
|
|
|
|
// ���� ����� �������� �� ������� ����.
|
|
|
|
function CloneNode(aDeep: Boolean = True): IXmlNode;
|
|
|
|
|
|
|
|
// Get_ParentNode - ���������� ������������ ����
|
|
|
|
function Get_ParentNode: IXmlNode;
|
|
|
|
// Get_OwnerDocument - ���������� XML-��������,
|
|
|
|
// � ������� ���������� ������ ����
|
|
|
|
function Get_OwnerDocument: IXmlDocument;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function Get_NextSibling: IXmlNode;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
// Get_ChildNodes - ���������� ������ �������� �����
|
|
|
|
function Get_ChildNodes: IXmlNodeList;
|
|
|
|
// AppendChild - ��������� ��������� ���� � ����� ������ �������� �����
|
|
|
|
procedure AppendChild(const aChild: IXmlNode);
|
|
|
|
// InsertBefore - ��������� ��������� ���� � ��������� ����� ������ �������� �����
|
|
|
|
procedure InsertBefore(const aChild, aBefore: IXmlNode);
|
|
|
|
// ReplaceChild - �������� ��������� ���� ������ �����
|
|
|
|
procedure ReplaceChild(const aNewChild, anOldChild: IXmlNode);
|
|
|
|
// RemoveChild - ������� ��������� ���� �� ������ �������� �����
|
|
|
|
procedure RemoveChild(const aChild: IXmlNode);
|
|
|
|
|
|
|
|
// AppendElement - ������� ������� � ��������� ��� � ����� ������
|
|
|
|
// � ����� ������ �������� ��������
|
|
|
|
function AppendElement(aNameID: Integer): IXmlElement; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function AppendElement(const aName: String): IXmlElement; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// AppendText - ������� ��������� ���� � ��������� ���
|
|
|
|
// � ����� ������ �������� ��������
|
2013-05-31 16:03:11 +06:00
|
|
|
function AppendText(const aData: String): IXmlText;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// AppendCDATA - ������� ������ CDATA � ��������� ��
|
|
|
|
// � ����� ������ �������� ��������
|
2013-05-31 16:03:11 +06:00
|
|
|
function AppendCDATA(const aData: String): IXmlCDATASection;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// AppendComment - ������� ����������� � ��������� ���
|
|
|
|
// � ����� ������ �������� ��������
|
2013-05-31 16:03:11 +06:00
|
|
|
function AppendComment(const aData: String): IXmlComment;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// AppendProcessingInstruction - ������� ���������� � ��������� ��
|
|
|
|
// � ����� ������ �������� ��������
|
|
|
|
function AppendProcessingInstruction(aTargetID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String): IXmlProcessingInstruction; overload;
|
|
|
|
function AppendProcessingInstruction(const aTarget: String;
|
|
|
|
const aData: String): IXmlProcessingInstruction; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetChildText - ���������� �������� ��������� ����
|
|
|
|
// SetChildText - ��������� ��� �������� �������� ��������� ����
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetChildText(const aName: String; const aDefault: String = ''): String; overload;
|
|
|
|
function GetChildText(aNameID: Integer; const aDefault: String = ''): String; overload;
|
|
|
|
procedure SetChildText(const aName, aValue: String); overload;
|
|
|
|
procedure SetChildText(aNameID: Integer; const aValue: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// NeedChild - ���������� �������� ���� � ��������� ������.
|
|
|
|
// ���� ���� �� ������, �� ������������ ����������
|
|
|
|
function NeedChild(aNameID: Integer): IXmlNode; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedChild(const aName: String): IXmlNode; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// EnsureChild - ���������� �������� ���� � ��������� ������.
|
|
|
|
// ���� ���� �� ������, �� �� ����� ������
|
|
|
|
function EnsureChild(aNameID: Integer): IXmlNode; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function EnsureChild(const aName: String): IXmlNode; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// RemoveAllChilds - ������� ��� �������� ����
|
|
|
|
procedure RemoveAllChilds;
|
|
|
|
|
|
|
|
// SelectNodes - ���������� ������� �����, ���������������
|
|
|
|
// ��������� ���������
|
2013-05-31 16:03:11 +06:00
|
|
|
function SelectNodes(const anExpression: String): IXmlNodeList; overload;
|
2010-11-06 22:21:34 +02:00
|
|
|
function SelectNodes(aNodeNameID: Integer): IXmlNodeList; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
// SelectSingleNode - ���������� ����� ������� ����, ����������������
|
|
|
|
// ��������� ���������
|
2013-05-31 16:03:11 +06:00
|
|
|
function SelectSingleNode(const anExpression: String): IXmlNode;
|
2010-11-06 22:16:58 +02:00
|
|
|
// FindElement - ���������� ����� ������� ����, ����������������
|
|
|
|
// ��������� ���������
|
|
|
|
function FindElement(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlElement;
|
2010-11-06 22:21:34 +02:00
|
|
|
function FindElements(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlNodeList;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// Get_AttrCount - ���������� ���������� ���������
|
|
|
|
function Get_AttrCount: Integer;
|
|
|
|
// Get_AttrNameID - ���������� ��� �������� ��������
|
|
|
|
function Get_AttrNameID(anIndex: Integer): Integer;
|
|
|
|
// Get_AttrName - ���������� �������� ��������
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_AttrName(anIndex: Integer): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
// RemoveAttr - ������� �������
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure RemoveAttr(const aName: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure RemoveAttr(aNameID: Integer); overload;
|
|
|
|
// RemoveAllAttrs - ������� ��� ��������
|
|
|
|
procedure RemoveAllAttrs;
|
|
|
|
|
|
|
|
// AttrExists - ���������, ����� �� ��������� �������.
|
|
|
|
function AttrExists(aNameID: Integer): Boolean; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function AttrExists(const aName: String): Boolean; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetAttrType - ���������� ��� ������ �������� � �������� ���������
|
|
|
|
function GetAttrType(aNameID: Integer): Integer; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetAttrType(const aName: String): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetAttrType - ���������� ��� ��������
|
|
|
|
// Result
|
|
|
|
// GetVarAttr - ���������� �������������� �������� ���������� ��������.
|
|
|
|
// ���� ������� �� �����, �� ������������ �������� �� ���������
|
|
|
|
// SetAttr - �������� ��� ��������� ��������� �������
|
|
|
|
function GetVarAttr(aNameID: Integer; const aDefault: Variant): Variant; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetVarAttr(const aName: String; const aDefault: Variant): Variant; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetVarAttr(aNameID: Integer; const aValue: Variant); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetVarAttr(const aName: String; aValue: Variant); overload;
|
2010-11-06 22:21:34 +02:00
|
|
|
function NeedVarAttr(aNameID: Integer): Variant; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedVarAttr(const aName: String): Variant; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// NeedAttr - ���������� ��������� �������� ���������� ��������.
|
|
|
|
// ���� ������� �� �����, �� ������������ ����������
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedAttr(aNameID: Integer): String; overload;
|
|
|
|
function NeedAttr(const aName: String): String; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetAttr - ���������� ��������� �������� ���������� ��������.
|
|
|
|
// ���� ������� �� �����, �� ������������ �������� �� ���������
|
|
|
|
// SetAttr - �������� ��� ��������� ��������� �������
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetAttr(aNameID: Integer; const aDefault: String = ''): String; overload;
|
|
|
|
function GetAttr(const aName: String; const aDefault: String = ''): String; overload;
|
|
|
|
procedure SetAttr(aNameID: Integer; const aValue: String); overload;
|
|
|
|
procedure SetAttr(const aName, aValue: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetBoolAttr - ���������� ������������� �������� ���������� ��������
|
|
|
|
// SetBoolAttr - �������� ��� ��������� ��������� ������� �������������
|
|
|
|
// ���������
|
|
|
|
function GetBoolAttr(aNameID: Integer; aDefault: Boolean = False): Boolean; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetBoolAttr(const aName: String; aDefault: Boolean = False): Boolean; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetBoolAttr(aNameID: Integer; aValue: Boolean = False); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetBoolAttr(const aName: String; aValue: Boolean); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetIntAttr - ���������� ������������� �������� ���������� ��������
|
|
|
|
// SetIntAttr - �������� ��� ��������� ��������� ������� �������������
|
|
|
|
// ���������
|
|
|
|
function GetIntAttr(aNameID: Integer; aDefault: Integer = 0): Integer; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetIntAttr(const aName: String; aDefault: Integer = 0): Integer; overload;
|
|
|
|
function NeedIntAttr(const aName: String): Integer; overload;
|
|
|
|
function NeedIntAttr(aNameID: Integer): Integer; overload;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetIntAttr(aNameID: Integer; aValue: Integer); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetIntAttr(const aName: String; aValue: Integer); overload;
|
|
|
|
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetDateTimeAttr - ���������� ������������� �������� ���������� ��������
|
|
|
|
// SetDateTimeAttr - �������� ��� ��������� ��������� ������� �������������
|
|
|
|
// ���������
|
|
|
|
function GetDateTimeAttr(aNameID: Integer; aDefault: TDateTime = 0): TDateTime; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetDateTimeAttr(const aName: String; aDefault: TDateTime = 0): TDateTime; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetDateTimeAttr(aNameID: Integer; aValue: TDateTime); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetDateTimeAttr(const aName: String; aValue: TDateTime); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetFloatAttr - ���������� �������� ���������� �������� � ����
|
|
|
|
// ������������� �����
|
|
|
|
// SetFloatAttr - �������� ��� ��������� ��������� ������� ������������
|
|
|
|
// ���������
|
|
|
|
function GetFloatAttr(aNameID: Integer; aDefault: Double = 0): Double; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetFloatAttr(const aName: String; aDefault: Double = 0): Double; overload;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
|
|
|
function NeedFloatAttr(aNameID: Integer): Double; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedFloatAttr(const aName: String): Double; overload;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetFloatAttr(aNameID: Integer; aValue: Double); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetFloatAttr(const aName: String; aValue: Double); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// GetHexAttr - ��������� �������� ���������� �������� � ������������� ����.
|
|
|
|
// ��������� �������� �������� ������������� � ����� �����. ��������
|
|
|
|
// ������ ������ ���� ������ � ����������������� ���� ��� ���������
|
|
|
|
// ("$", "0x" � ��.) ���� �������������� �� ����� ���� ���������,
|
|
|
|
// ������������ ����������.
|
|
|
|
// ���� ������� �� �����, ������������ �������� ��������� aDefault.
|
|
|
|
// SetHexAttr - ��������� �������� ���������� �������� �� ���������
|
|
|
|
// ������������� ������ ����� � ����������������� ���� ��� ���������
|
|
|
|
// ("$", "0x" � ��.) ���� �������������� �� ����� ���� ���������,
|
|
|
|
// ������������ ����������.
|
|
|
|
// ���� ������� �� ��� �����, �� �� ����� ��������.
|
|
|
|
// ���� ��� �����, �� ����� �������.
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetHexAttr(const aName: String; aDefault: Integer = 0): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function GetHexAttr(aNameID: Integer; aDefault: Integer = 0): Integer; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetHexAttr(const aName: String; aValue: Integer; aDigits: Integer = 8); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetHexAttr(aNameID: Integer; aValue: Integer; aDigits: Integer = 8); overload;
|
|
|
|
|
|
|
|
// GetEnumAttr - ���� �������� �������� � ��������� ������ ����� �
|
|
|
|
// ���������� ������ ��������� ������. ���� ������� ����� �� �� ������
|
|
|
|
// � ������, �� ������������ ����������.
|
|
|
|
// ���� ������� �� �����, ������������ �������� ��������� aDefault.
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetEnumAttr(const aName: String;
|
|
|
|
const aValues: array of String; aDefault: Integer = 0): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function GetEnumAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aValues: array of String; aDefault: Integer = 0): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedEnumAttr(const aName: String;
|
|
|
|
const aValues: array of String): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function NeedEnumAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aValues: array of String): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
// ReplaceTextByCDATASection - ������� ��� ��������� �������� � ���������
|
|
|
|
// ���� ������ CDATA, ���������� ��������� �����
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure ReplaceTextByCDATASection(const aText: String);
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
// ReplaceTextByBinaryData - ������� ��� ��������� �������� � ���������
|
2010-11-06 22:21:34 +02:00
|
|
|
// ���� ��������� �������, ���������� ��������� �������� ������
|
|
|
|
// � ������� "base64".
|
|
|
|
// ���� �������� aMaxLineLength �� ����� ����, �� ������������ ��������
|
|
|
|
// ��������� ������ �� ������ ������ aMaxLineLength.
|
|
|
|
// ������ ����������� ����� �������� #13#10 (CR,LF).
|
|
|
|
// ����� ��������� ������ ��������� ������� �� �����������.
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure ReplaceTextByBinaryData(const aData; aSize: Integer;
|
2010-11-06 22:21:34 +02:00
|
|
|
aMaxLineLength: Integer);
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
// GetTextAsBinaryData - c������� ��� ��������� �������� � ���� ������ �
|
2010-11-06 22:21:34 +02:00
|
|
|
// ���������� �������������� �� ������� "base64" � �������� ������.
|
|
|
|
// ��� �������������� ������������ ��� ���������� ������� (� ����� <= ' '),
|
|
|
|
// ������������ � �������� ������.
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetTextAsBinaryData: RawByteString;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetOwnText: String;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function Get_Values(const aName: String): Variant;
|
|
|
|
procedure Set_Values(const aName: String; const aValue: Variant);
|
|
|
|
|
|
|
|
function AsElement: IXmlElement;
|
|
|
|
function AsText: IXmlText;
|
|
|
|
function AsCDATASection: IXmlCDATASection;
|
|
|
|
function AsComment: IXmlComment;
|
|
|
|
function AsProcessingInstruction: IXmlProcessingInstruction;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
property SourceLine: Integer read Get_SourceLine;
|
|
|
|
property SourceCol: Integer read Get_SourceCol;
|
2013-05-31 16:03:11 +06:00
|
|
|
property NodeName: String read Get_NodeName;
|
2010-11-06 22:16:58 +02:00
|
|
|
property NodeNameID: Integer read Get_NodeNameID;
|
|
|
|
property NodeType: Integer read Get_NodeType;
|
|
|
|
property ParentNode: IXmlNode read Get_ParentNode;
|
|
|
|
property OwnerDocument: IXmlDocument read Get_OwnerDocument;
|
2010-11-06 22:21:34 +02:00
|
|
|
property NextSibling: IXmlNode read Get_NextSibling;
|
2010-11-06 22:16:58 +02:00
|
|
|
property NameTable: IXmlNameTable read Get_NameTable;
|
|
|
|
property ChildNodes: IXmlNodeList read Get_ChildNodes;
|
|
|
|
property AttrCount: Integer read Get_AttrCount;
|
2013-05-31 16:03:11 +06:00
|
|
|
property AttrNames[anIndex: Integer]: String read Get_AttrName;
|
2010-11-06 22:16:58 +02:00
|
|
|
property AttrNameIDs[anIndex: Integer]: Integer read Get_AttrNameID;
|
2013-05-31 16:03:11 +06:00
|
|
|
property Text: String read Get_Text write Set_Text;
|
2010-11-06 22:16:58 +02:00
|
|
|
property DataType: Integer read Get_DataType;
|
|
|
|
property TypedValue: Variant read Get_TypedValue write Set_TypedValue;
|
2013-05-31 16:03:11 +06:00
|
|
|
property Xml: String read Get_Xml;
|
2010-11-06 22:16:58 +02:00
|
|
|
property Values[const aName: String]: Variant read Get_Values write Set_Values; default;
|
|
|
|
end;
|
|
|
|
|
|
|
|
IXmlElement = interface(IXmlNode)
|
|
|
|
end;
|
|
|
|
|
|
|
|
IXmlCharacterData = interface(IXmlNode)
|
|
|
|
end;
|
|
|
|
|
|
|
|
IXmlText = interface(IXmlCharacterData)
|
|
|
|
end;
|
|
|
|
|
|
|
|
IXmlCDATASection = interface(IXmlCharacterData)
|
|
|
|
end;
|
|
|
|
|
|
|
|
IXmlComment = interface(IXmlCharacterData)
|
|
|
|
end;
|
|
|
|
|
|
|
|
IXmlProcessingInstruction = interface(IXmlNode)
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Target: String;
|
|
|
|
|
|
|
|
property Target: String read Get_Target;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
IXmlDocument = interface(IXmlNode)
|
|
|
|
function Get_DocumentElement: IXmlElement;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_BinaryXML: RawByteString;
|
2010-11-06 22:16:58 +02:00
|
|
|
function Get_PreserveWhiteSpace: Boolean;
|
|
|
|
procedure Set_PreserveWhiteSpace(aValue: Boolean);
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function NewDocument(const aVersion, anEncoding: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aRootElementNameID: Integer): IXmlElement; overload;
|
|
|
|
function NewDocument(const aVersion, anEncoding,
|
2013-05-31 16:03:11 +06:00
|
|
|
aRootElementName: String): IXmlElement; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function CreateElement(aNameID: Integer): IXmlElement; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function CreateElement(const aName: String): IXmlElement; overload;
|
|
|
|
function CreateText(const aData: String): IXmlText;
|
|
|
|
function CreateCDATASection(const aData: String): IXmlCDATASection;
|
|
|
|
function CreateComment(const aData: String): IXmlComment;
|
2010-11-06 22:16:58 +02:00
|
|
|
function CreateProcessingInstruction(const aTarget,
|
2013-05-31 16:03:11 +06:00
|
|
|
aData: String): IXmlProcessingInstruction; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function CreateProcessingInstruction(aTargetID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String): IXmlProcessingInstruction; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure LoadXML(const anXml: String); overload;
|
|
|
|
procedure LoadXML(const anXml: RawByteString); overload;
|
|
|
|
procedure LoadBinaryXML(const anXml: RawByteString);
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure Load(aStream: TStream); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure Load(const aFileName: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure LoadResource(aType, aName: PChar);
|
|
|
|
|
|
|
|
procedure Save(aStream: TStream); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure Save(const aFileName: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure SaveBinary(aStream: TStream; anOptions: LongWord = 0); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SaveBinary(const aFileName: String; anOptions: LongWord = 0); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
property PreserveWhiteSpace: Boolean read Get_PreserveWhiteSpace write Set_PreserveWhiteSpace;
|
|
|
|
property DocumentElement: IXmlElement read Get_DocumentElement;
|
2013-05-31 16:03:11 +06:00
|
|
|
property BinaryXML: RawByteString read Get_BinaryXML;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function CreateNameTable(aHashTableSize: Integer = 4096): IXmlNameTable;
|
|
|
|
function CreateXmlDocument(
|
|
|
|
const aRootElementName: String = '';
|
|
|
|
const aVersion: String = '1.0';
|
|
|
|
const anEncoding: String = ''; // SimpleXmlDefaultEncoding
|
|
|
|
const aNames: IXmlNameTable = nil): IXmlDocument;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function CreateXmlElement(const aName: String; const aNameTable: IXmlNameTable = nil): IXmlElement;
|
2010-11-06 22:21:34 +02:00
|
|
|
function CreateXmlNodeList: IXmlNodeList;
|
2013-05-31 16:03:11 +06:00
|
|
|
function LoadXmlDocumentFromXml(const anXml: String): IXmlDocument;
|
|
|
|
function LoadXmlDocumentFromBinaryXML(const aBinaryXml: RawByteString): IXmlDocument;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function LoadXmlDocument(aStream: TStream): IXmlDocument; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function LoadXmlDocument(const aFileName: String): IXmlDocument; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function LoadXmlDocument(aResType, aResName: PChar): IXmlDocument; overload;
|
|
|
|
|
|
|
|
var
|
|
|
|
DefaultNameTable: IXmlNameTable = nil;
|
|
|
|
DefaultPreserveWhiteSpace: Boolean = False;
|
|
|
|
DefaultEncoding: String = 'windows-1251';
|
|
|
|
DefaultIndentText: String = ^I;
|
|
|
|
|
|
|
|
resourcestring
|
|
|
|
SSimpleXmlError1 = '������ ��������� �������� ������: ������ ������� �� �������';
|
|
|
|
SSimpleXmlError2 = '�� ��������� ����������� ��������';
|
|
|
|
SSimpleXmlError3 = '����������� ������ � ����� ��������';
|
|
|
|
SSimpleXmlError4 = '������ ������ ��������� XML: ������������ ��� ����';
|
|
|
|
SSimpleXmlError5 = '������ ������ ��������� XML: ������������ ��� ����';
|
|
|
|
SSimpleXmlError6 = '�������� �������� �������� "%s" �������� "%s".'^M^J +
|
|
|
|
'���������� ��������:'^M^J +
|
|
|
|
'%s';
|
|
|
|
SSimpleXmlError7 = '�� ������ ������� "%s"';
|
|
|
|
SSimpleXmlError8 = '�� ����� ������� "%s"';
|
|
|
|
SSimpleXmlError9 = '������ ����������� �� �������������� SimpleXML';
|
|
|
|
SSimpleXmlError10 = '������: �� ������ �������� ������� "%s".';
|
2010-11-06 22:21:34 +02:00
|
|
|
SSimpleXmlError11 = '��� ������ ���������� � ����� ��� "_" (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError12 = '��������� ����� (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError13 = '��������� ����������������� ����� (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError14 = '��������� "#" ��� ��� ������������ ������� (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError15 = '������������ ��� ������������ ������� (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError16 = '��������� "%s" (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError17 = '��������� "%s" (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError18 = '������ "<" �� ����� �������������� � ��������� ��������� (���. %d, ���. %d)';
|
|
|
|
SimpleXmlError19 = '��������� "%s" (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError20 = '��������� �������� �������� (���. %d, ���. %d)';
|
|
|
|
SSimpleXmlError21 = '��������� ��������� ��������� (���. %d, ���. %d)';
|
|
|
|
SimpleXmlError22 = '��������� "%s" (���. %d, ���. %d)';
|
2010-11-06 22:16:58 +02:00
|
|
|
SSimpleXmlError23 = '������ ������ ������.';
|
|
|
|
SSimpleXmlError24 = '������ ������ ��������: ������������ ���.';
|
|
|
|
SSimpleXmlError25 = '������ ������ ��������: ������������ ���.';
|
2013-05-31 16:03:11 +06:00
|
|
|
SSimpleXmlError26 = '%s (����: "%s")';
|
|
|
|
SSimpleXmlError27 = '������ ��������� �������� ��������: �� ������ ���.';
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function XSTRToFloat(s: String): Double;
|
|
|
|
function FloatToXSTR(v: Double): String;
|
|
|
|
function DateTimeToXSTR(v: TDateTime): String;
|
|
|
|
function VarToXSTR(const v: TVarData): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TextToXML(const aText: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
function BinToBase64(const aBin; aSize, aMaxLineLength: Integer): String;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Base64ToBin(const aBase64: String): RawByteString;
|
|
|
|
|
|
|
|
function IsXmlDataString(const aData: RawByteString): Boolean;
|
|
|
|
function XmlIsInBinaryFormat(const aData: RawByteString): Boolean;
|
|
|
|
|
|
|
|
function AppendChildNodeFromXml(const aParentNode: IXmlNode; const anXml: String): IXmlNode;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
|
|
|
Variants, DateUtils;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
const
|
|
|
|
BinXmlSignatureSize = Length('< binary-xml >');
|
|
|
|
BinXmlSignature: RawByteString = '< binary-xml >';
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
type
|
|
|
|
TStringBuilder = object
|
|
|
|
private
|
2013-05-31 16:03:11 +06:00
|
|
|
FData: String;
|
2010-11-06 22:21:34 +02:00
|
|
|
FLength: Integer;
|
|
|
|
public
|
|
|
|
procedure Init;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure Add(const s: String);
|
|
|
|
procedure GetString(var aString: String);
|
2010-11-06 22:21:34 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
{ TStringBuilder }
|
|
|
|
|
|
|
|
procedure TStringBuilder.Init;
|
|
|
|
begin
|
|
|
|
FData := '';
|
|
|
|
FLength := 0;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TStringBuilder.Add(const s: String);
|
|
|
|
var
|
|
|
|
anAddLength,
|
|
|
|
aNewLength: Integer;
|
|
|
|
begin
|
|
|
|
anAddLength := Length(s);
|
2013-05-31 16:03:11 +06:00
|
|
|
if anAddLength = 0 then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
Exit;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
|
|
|
aNewLength := FLength + anAddLength;
|
2013-05-31 16:03:11 +06:00
|
|
|
if aNewLength > Length(FData) then begin
|
|
|
|
if aNewLength > 64 then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
SetLength(FData, aNewLength + aNewLength div 4)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if aNewLength > 8 then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
SetLength(FData, aNewLength + 16)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:21:34 +02:00
|
|
|
SetLength(FData, aNewLength + 4);
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
end;
|
|
|
|
Move(s[1], FData[FLength + 1], anAddLength*sizeof(Char));
|
2010-11-06 22:21:34 +02:00
|
|
|
FLength := aNewLength;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TStringBuilder.GetString(var aString: String);
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
aString := Copy(FData, 1, FLength);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure CopyChars(const aFrom: String; var aTo: String; var aPos: Integer);
|
|
|
|
begin
|
|
|
|
Move(aFrom[1], aTo[aPos], Length(aFrom)*sizeof(Char));
|
|
|
|
Inc(aPos, Length(aFrom));
|
2010-11-06 22:21:34 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TextToXML(const aText: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i, j: Integer;
|
|
|
|
begin
|
|
|
|
j := 0;
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 1 to Length(aText) do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
case aText[i] of
|
|
|
|
'<', '>': Inc(j, 4);
|
|
|
|
'&': Inc(j, 5);
|
|
|
|
'"': Inc(j, 6);
|
2013-05-31 16:03:11 +06:00
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(j);
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
|
|
|
|
if j = Length(aText) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aText
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
SetLength(Result, j);
|
|
|
|
j := 1;
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 1 to Length(aText) do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
case aText[i] of
|
2013-05-31 16:03:11 +06:00
|
|
|
'<': begin CopyChars('<', Result, j) end;
|
|
|
|
'>': begin CopyChars('>', Result, j) end;
|
|
|
|
'&': begin CopyChars('&', Result, j) end;
|
|
|
|
'"': begin CopyChars('"', Result, j) end;
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin Result[j] := aText[i]; Inc(j) end;
|
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function XSTRToFloat(s: String): Double;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aPos: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if '.' = FormatSettings.DecimalSeparator then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aPos := Pos(',', s)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if ',' = FormatSettings.DecimalSeparator then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aPos := Pos('.', s)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
aPos := Pos(',', s);
|
2013-05-31 16:03:11 +06:00
|
|
|
if aPos = 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aPos := Pos('.', s);
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
if aPos <> 0 then begin
|
|
|
|
s[aPos] := FormatSettings.DecimalSeparator;
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := StrToFloat(s);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function FloatToXSTR(v: Double): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aPos: Integer;
|
|
|
|
begin
|
|
|
|
Result := FloatToStr(v);
|
2013-05-31 16:03:11 +06:00
|
|
|
aPos := Pos(FormatSettings.DecimalSeparator, Result);
|
|
|
|
if aPos <> 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result[aPos] := '.';
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function IsDigit(c: Char): Boolean;
|
|
|
|
begin
|
|
|
|
Result := (c >= '0') and (c <= '9')
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function XSTRToDateTime(const s: String): TDateTime;
|
|
|
|
var
|
|
|
|
aPos: Integer;
|
|
|
|
|
|
|
|
function FetchTo(aStop: Char): Integer;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
i := aPos;
|
2013-05-31 16:03:11 +06:00
|
|
|
while (i <= Length(s)) and IsDigit(s[i]) do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(i);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
if i > aPos then
|
|
|
|
Result := StrToInt(Copy(s, aPos, i - aPos))
|
|
|
|
else
|
|
|
|
Result := 0;
|
|
|
|
if (i <= Length(s)) and (s[i] = aStop) then
|
|
|
|
aPos := i + 1
|
|
|
|
else
|
|
|
|
aPos := Length(s) + 1;
|
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
y, m, d, h, n, ss: Integer;
|
|
|
|
begin
|
|
|
|
aPos := 1;
|
|
|
|
y := FetchTo('-'); m := FetchTo('-'); d := FetchTo('T');
|
|
|
|
h := FetchTo('-'); n := FetchTo('-'); ss := FetchTo('-');
|
|
|
|
Result := EncodeDateTime(y, m, d, h, n, ss, 0);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function DateTimeToXSTR(v: TDateTime): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
y, m, d, h, n, s, ms: Word;
|
|
|
|
begin
|
|
|
|
DecodeDateTime(v, y, m, d, h, n, s, ms);
|
2013-05-31 16:03:11 +06:00
|
|
|
Result := Format('%.4d-%.2d-%.2dT%.2d:%.2d:%.2d', [y, m, d, h, n, s])
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function VarToXSTR(const v: TVarData): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
const
|
2013-05-31 16:03:11 +06:00
|
|
|
BoolStr: array[Boolean] of String = ('0', '1');
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
p: Pointer;
|
|
|
|
begin
|
|
|
|
case v.VType of
|
|
|
|
varNull: Result := XSTR_NULL;
|
|
|
|
varSmallint: Result := IntToStr(v.VSmallInt);
|
|
|
|
varInteger: Result := IntToStr(v.VInteger);
|
|
|
|
varSingle: Result := FloatToXSTR(v.VSingle);
|
|
|
|
varDouble: Result := FloatToXSTR(v.VDouble);
|
|
|
|
varCurrency: Result := FloatToXSTR(v.VCurrency);
|
|
|
|
varDate: Result := DateTimeToXSTR(v.VDate);
|
|
|
|
varOleStr: Result := v.VOleStr;
|
|
|
|
varBoolean: Result := BoolStr[v.VBoolean = True];
|
|
|
|
varShortInt: Result := IntToStr(v.VShortInt);
|
|
|
|
varByte: Result := IntToStr(v.VByte);
|
|
|
|
varWord: Result := IntToStr(v.VWord);
|
|
|
|
varLongWord: Result := IntToStr(v.VLongWord);
|
|
|
|
varInt64: Result := IntToStr(v.VInt64);
|
2013-05-31 16:03:11 +06:00
|
|
|
varString: Result := String(AnsiString(v.VString));
|
|
|
|
varUString: Result := String(v.VString);
|
|
|
|
varArray + varByte: begin
|
|
|
|
p := VarArrayLock(Variant(v));
|
|
|
|
try
|
|
|
|
Result := BinToBase64(p^, VarArrayHighBound(Variant(v), 1) - VarArrayLowBound(Variant(v), 1) + 1, 0);
|
|
|
|
finally
|
|
|
|
VarArrayUnlock(Variant(v))
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := Variant(v)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function LoadXMLResource(aModule: HMODULE; aName, aType: PChar; const aXMLDoc: IXmlDocument): boolean;
|
|
|
|
var
|
|
|
|
aRSRC: HRSRC;
|
|
|
|
aGlobal: HGLOBAL;
|
|
|
|
aSize: DWORD;
|
|
|
|
aPointer: Pointer;
|
|
|
|
|
|
|
|
aStream: TStringStream;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
|
|
|
aRSRC := FindResource(aModule, aName, aType);
|
|
|
|
if aRSRC <> 0 then begin
|
|
|
|
aGlobal := LoadResource(aModule, aRSRC);
|
|
|
|
aSize := SizeofResource(aModule, aRSRC);
|
|
|
|
if (aGlobal <> 0) and (aSize <> 0) then begin
|
|
|
|
aPointer := LockResource(aGlobal);
|
|
|
|
if Assigned(aPointer) then begin
|
|
|
|
aStream := TStringStream.Create('');
|
|
|
|
try
|
|
|
|
aStream.WriteBuffer(aPointer^, aSize);
|
|
|
|
aXMLDoc.LoadXML(aStream.DataString);
|
|
|
|
Result := true;
|
|
|
|
finally
|
|
|
|
aStream.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function IsWhitespace(c: Char): Boolean;
|
|
|
|
begin
|
|
|
|
Result := c <= ' ';
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function IsAnsiWhitespace(c: AnsiChar): Boolean;
|
|
|
|
begin
|
|
|
|
Result := c <= ' ';
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function IsXmlDataString(const aData: RawByteString): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
Result := Copy(aData, 1, BinXmlSignatureSize) = BinXmlSignature;
|
|
|
|
if not Result then begin
|
|
|
|
i := 1;
|
2013-05-31 16:03:11 +06:00
|
|
|
while (i <= Length(aData)) and IsAnsiWhitespace(aData[i]) do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(i);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := Copy(aData, i, Length('<?xml ')) = '<?xml ';
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function XmlIsInBinaryFormat(const aData: RawByteString): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := Copy(aData, 1, BinXmlSignatureSize) = BinXmlSignature
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
Base64Map: array [0..63] of Char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
|
|
|
|
|
|
type
|
|
|
|
PChars = ^TChars;
|
|
|
|
TChars = packed record a, b, c, d: Char end;
|
|
|
|
POctet = ^TOctet;
|
|
|
|
TOctet = packed record a, b, c: Byte; end;
|
|
|
|
|
|
|
|
procedure OctetToChars(po: POctet; aCount: Integer; pc: PChars);
|
|
|
|
var
|
|
|
|
o: Integer;
|
|
|
|
begin
|
|
|
|
if aCount = 1 then begin
|
|
|
|
o := po.a shl 16;
|
|
|
|
pc.a := Base64Map[(o shr 18) and $3F];
|
|
|
|
pc.b := Base64Map[(o shr 12) and $3F];
|
2013-05-31 16:03:11 +06:00
|
|
|
pc.c := '=';
|
|
|
|
pc.d := '=';
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
|
|
|
else if aCount = 2 then begin
|
|
|
|
o := po.a shl 16 or po.b shl 8;
|
|
|
|
pc.a := Base64Map[(o shr 18) and $3F];
|
|
|
|
pc.b := Base64Map[(o shr 12) and $3F];
|
|
|
|
pc.c := Base64Map[(o shr 6) and $3F];
|
2013-05-31 16:03:11 +06:00
|
|
|
pc.d := '=';
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
|
|
|
else if aCount > 2 then begin
|
|
|
|
o := po.a shl 16 or po.b shl 8 or po.c;
|
|
|
|
pc.a := Base64Map[(o shr 18) and $3F];
|
|
|
|
pc.b := Base64Map[(o shr 12) and $3F];
|
|
|
|
pc.c := Base64Map[(o shr 6) and $3F];
|
|
|
|
pc.d := Base64Map[o and $3F];
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function BinToBase64(const aBin; aSize, aMaxLineLength: Integer): String;
|
|
|
|
var
|
|
|
|
o: POctet;
|
|
|
|
c: PChars;
|
|
|
|
aCount: Integer;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
o := @aBin;
|
|
|
|
aCount := aSize;
|
|
|
|
SetLength(Result, ((aCount + 2) div 3)*4);
|
|
|
|
c := PChars(Result);
|
|
|
|
while aCount > 0 do begin
|
|
|
|
OctetToChars(o, aCount, c);
|
|
|
|
Inc(o);
|
|
|
|
Inc(c);
|
|
|
|
Dec(aCount, 3);
|
|
|
|
end;
|
|
|
|
if aMaxLineLength > 0 then begin
|
|
|
|
i := aMaxLineLength;
|
|
|
|
while i <= Length(Result) do begin
|
|
|
|
Insert(#13#10, Result, i);
|
|
|
|
Inc(i, 2 + aMaxLineLength);
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function CharTo6Bit(c: Char): Byte;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if (c >= 'A') and (c <= 'Z') then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := Ord(c) - Ord('A')
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if (c >= 'a') and (c <= 'z') then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := Ord(c) - Ord('a') + 26
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if (c >= '0') and (c <= '9') then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := Ord(c) - Ord('0') + 52
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if c = '+' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := 62
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if c = '/' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := 63
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := 0
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure CharsToOctet(c: PChars; o: POctet);
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
if c.c = '=' then begin // 1 byte
|
|
|
|
i := CharTo6Bit(c.a) shl 18 or CharTo6Bit(c.b) shl 12;
|
|
|
|
o.a := (i shr 16) and $FF;
|
|
|
|
end
|
|
|
|
else if c.d = '=' then begin // 2 bytes
|
|
|
|
i := CharTo6Bit(c.a) shl 18 or CharTo6Bit(c.b) shl 12 or CharTo6Bit(c.c) shl 6;
|
|
|
|
o.a := (i shr 16) and $FF;
|
|
|
|
o.b := (i shr 8) and $FF;
|
|
|
|
end
|
|
|
|
else begin // 3 bytes
|
|
|
|
i := CharTo6Bit(c.a) shl 18 or CharTo6Bit(c.b) shl 12 or CharTo6Bit(c.c) shl 6 or CharTo6Bit(c.d);
|
|
|
|
o.a := (i shr 16) and $FF;
|
|
|
|
o.b := (i shr 8) and $FF;
|
|
|
|
o.c := i and $FF;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function Base64ToBin(const aBase64: String): RawByteString;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
o: POctet;
|
|
|
|
c: PChars;
|
|
|
|
aCount: Integer;
|
|
|
|
s: String;
|
|
|
|
i, j: Integer;
|
|
|
|
begin
|
|
|
|
s := aBase64;
|
|
|
|
i := 1;
|
|
|
|
while i <= Length(s) do begin
|
2013-05-31 16:03:11 +06:00
|
|
|
while (i <= Length(s)) and (s[i] > ' ') do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(i);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
if i <= Length(s) then begin
|
|
|
|
j := i;
|
2013-05-31 16:03:11 +06:00
|
|
|
while (j <= Length(s)) and (s[j] <= ' ') do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(j);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Delete(s, i, j - i);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
if Length(s) < 4 then begin
|
|
|
|
SetLength(Result, 0)
|
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
aCount := ((Length(s) + 3) div 4)*3;
|
|
|
|
if aCount > 0 then begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if s[Length(s) - 1] = '=' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Dec(aCount, 2)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if s[Length(s)] = '=' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Dec(aCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
SetLength(Result, aCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
FillChar(Result[1], aCount, 0);
|
2010-11-06 22:16:58 +02:00
|
|
|
c := @s[1];
|
|
|
|
o := @Result[1];
|
|
|
|
while aCount > 0 do begin
|
|
|
|
CharsToOctet(c, o);
|
|
|
|
Inc(o);
|
|
|
|
Inc(c);
|
|
|
|
Dec(aCount, 3);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
type
|
2013-05-31 16:03:11 +06:00
|
|
|
TBinaryXmlReader = class
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
|
|
|
FOptions: LongWord;
|
|
|
|
public
|
|
|
|
procedure Read(var aBuf; aSize: Integer); virtual; abstract;
|
2013-05-31 16:03:11 +06:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function ReadLongint: Longint;
|
2013-05-31 16:03:11 +06:00
|
|
|
function ReadAnsiString: AnsiString;
|
|
|
|
function ReadUnicodeString: UnicodeString;
|
|
|
|
function ReadXmlString: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure ReadVariant(var v: TVarData);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
TStreamBinaryXmlReader = class(TBinaryXmlReader)
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
|
|
|
FStream: TStream;
|
|
|
|
FOptions: LongWord;
|
|
|
|
FBufStart,
|
|
|
|
FBufEnd,
|
2013-05-31 16:03:11 +06:00
|
|
|
FBufPtr: PByte;
|
2010-11-06 22:16:58 +02:00
|
|
|
FBufSize,
|
|
|
|
FRestSize: Integer;
|
|
|
|
public
|
|
|
|
constructor Create(aStream: TStream; aBufSize: Integer);
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
procedure Read(var aBuf; aSize: Integer); override;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
TRawByteStringBinaryXmlReader = class(TBinaryXmlReader)
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
2013-05-31 16:03:11 +06:00
|
|
|
FString: RawByteString;
|
2010-11-06 22:16:58 +02:00
|
|
|
FOptions: LongWord;
|
2013-05-31 16:03:11 +06:00
|
|
|
FPtr: PByte;
|
2010-11-06 22:16:58 +02:00
|
|
|
FRestSize: Integer;
|
|
|
|
public
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor Create(const aStr: RawByteString);
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure Read(var aBuf; aSize: Integer); override;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
TBinaryXmlWriter = class
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
|
|
|
FOptions: LongWord;
|
|
|
|
public
|
|
|
|
procedure Write(const aBuf; aSize: Integer); virtual; abstract;
|
2013-05-31 16:03:11 +06:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure WriteLongint(aValue: Longint);
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure WriteAnsiString(const aValue: AnsiString);
|
|
|
|
procedure WriteUnicodeString(const aValue: UnicodeString);
|
|
|
|
procedure WriteXmlString(const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure WriteVariant(const v: TVarData);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
TStreamBinrayXmlWriter = class(TBinaryXmlWriter)
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
|
|
|
FStream: TStream;
|
|
|
|
FBufStart,
|
|
|
|
FBufEnd,
|
2013-05-31 16:03:11 +06:00
|
|
|
FBufPtr: PAnsiChar;
|
2010-11-06 22:16:58 +02:00
|
|
|
FBufSize: Integer;
|
|
|
|
public
|
|
|
|
constructor Create(aStream: TStream; anOptions: LongWord; aBufSize: Integer);
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
procedure Write(const aBuf; aSize: Integer); override;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
TRawByteStringBinaryXmlWriter = class(TBinaryXmlWriter)
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
2013-05-31 16:03:11 +06:00
|
|
|
FData: RawByteString;
|
2010-11-06 22:16:58 +02:00
|
|
|
FBufStart,
|
|
|
|
FBufEnd,
|
2013-05-31 16:03:11 +06:00
|
|
|
FBufPtr: PAnsiChar;
|
2010-11-06 22:16:58 +02:00
|
|
|
FBufSize: Integer;
|
|
|
|
procedure FlushBuf;
|
|
|
|
public
|
|
|
|
constructor Create(anOptions: LongWord; aBufSize: Integer);
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
procedure Write(const aBuf; aSize: Integer); override;
|
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
TXmlBase = class(TInterfacedObject, IXmlBase)
|
|
|
|
protected
|
|
|
|
// ���������� ���������� IXmlBase
|
|
|
|
function GetObject: TObject;
|
|
|
|
public
|
|
|
|
end;
|
|
|
|
|
|
|
|
PNameIndexArray = ^TNameIndexArray;
|
|
|
|
TNameIndexArray = array of Longint;
|
|
|
|
TXmlNameTable = class(TXmlBase, IXmlNameTable)
|
|
|
|
private
|
2013-05-31 16:03:11 +06:00
|
|
|
FNames: array of String;
|
2010-11-06 22:16:58 +02:00
|
|
|
FHashTable: array of TNameIndexArray;
|
|
|
|
|
|
|
|
FXmlTextNameID: Integer;
|
|
|
|
FXmlCDATASectionNameID: Integer;
|
|
|
|
FXmlCommentNameID: Integer;
|
|
|
|
FXmlDocumentNameID: Integer;
|
|
|
|
FXmlID: Integer;
|
|
|
|
protected
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetID(const aName: String): Integer;
|
|
|
|
function GetName(anID: Integer): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
public
|
|
|
|
constructor Create(aHashTableSize: Integer);
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure LoadBinXml(aReader: TBinaryXmlReader);
|
|
|
|
procedure SaveBinXml(aWriter: TBinaryXmlWriter);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlBase }
|
|
|
|
|
|
|
|
function TXmlBase.GetObject: TObject;
|
|
|
|
begin
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlNameTable }
|
|
|
|
|
|
|
|
constructor TXmlNameTable.Create(aHashTableSize: Integer);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
SetLength(FHashTable, aHashTableSize);
|
|
|
|
FXmlTextNameID := GetID('#text');
|
|
|
|
FXmlCDATASectionNameID := GetID('#cdata-section');
|
|
|
|
FXmlCommentNameID := GetID('#comment');
|
|
|
|
FXmlDocumentNameID := GetID('#document');
|
|
|
|
FXmlID := GetID('xml');
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNameTable.LoadBinXml(aReader: TBinaryXmlReader);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aCount: LongInt;
|
|
|
|
anIndex, i: Integer;
|
|
|
|
begin
|
|
|
|
// ������� ������ ����
|
|
|
|
aCount := aReader.ReadLongint;
|
|
|
|
SetLength(FNames, aCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to aCount - 1 do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
FNames[i] := aReader.ReadXmlString;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// ������� ���-�������
|
|
|
|
SetLength(FHashTable, aReader.ReadLongint);
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to Length(FHashTable) - 1 do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
SetLength(FHashTable[i], 0);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
aCount := aReader.ReadLongint;
|
|
|
|
for i := 0 to aCount - 1 do begin
|
|
|
|
anIndex := aReader.ReadLongInt;
|
|
|
|
SetLength(FHashTable[anIndex], aReader.ReadLongInt);
|
|
|
|
aReader.Read(FHashTable[anIndex][0], Length(FHashTable[anIndex])*sizeof(Longint));
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNameTable.SaveBinXml(aWriter: TBinaryXmlWriter);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aCount: LongInt;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
// �������� ������ ����
|
|
|
|
aCount := Length(FNames);
|
|
|
|
aWriter.WriteLongint(aCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to aCount - 1 do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aWriter.WriteXmlString(FNames[i]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// �������� ���-�������
|
|
|
|
aWriter.WriteLongint(Length(FHashTable));
|
|
|
|
aCount := 0;
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to Length(FHashTable) - 1 do begin
|
|
|
|
if Length(FHashTable[i]) > 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(aCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
aWriter.WriteLongint(aCount);
|
|
|
|
for i := 0 to Length(FHashTable) - 1 do begin
|
|
|
|
aCount := Length(FHashTable[i]);
|
|
|
|
if aCount > 0 then begin
|
|
|
|
aWriter.WriteLongint(i);
|
|
|
|
aWriter.WriteLongint(aCount);
|
|
|
|
aWriter.Write(FHashTable[i][0], aCount*sizeof(Longint));
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNameTable.GetID(const aName: String): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function NameHashKey(const aName: String): UINT;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
Result := 0;
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 1 to Length(aName) do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := UINT((int64(Result) shl 5) + Result + Ord(aName[i]));
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aNameIndexes: PNameIndexArray;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if aName = '' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := -1
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
aNameIndexes := @FHashTable[NameHashKey(aName) mod UINT(Length(FHashTable))];
|
|
|
|
for i := 0 to Length(aNameIndexes^) - 1 do begin
|
|
|
|
Result := aNameIndexes^[i];
|
2013-05-31 16:03:11 +06:00
|
|
|
if FNames[Result] = aName then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Exit
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
Result := Length(FNames);
|
|
|
|
SetLength(FNames, Result + 1);
|
|
|
|
FNames[Result] := aName;
|
|
|
|
|
|
|
|
SetLength(aNameIndexes^, Length(aNameIndexes^) + 1);
|
|
|
|
aNameIndexes^[Length(aNameIndexes^) - 1] := Result;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNameTable.GetName(anID: Integer): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if anID < 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := ''
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := FNames[anID]
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function CreateNameTable(aHashTableSize: Integer): IXmlNameTable;
|
|
|
|
begin
|
|
|
|
Result := TXmlNameTable.Create(aHashTableSize)
|
|
|
|
end;
|
|
|
|
|
|
|
|
type
|
|
|
|
TXmlNode = class;
|
|
|
|
TXmlToken = class
|
|
|
|
private
|
2013-05-31 16:03:11 +06:00
|
|
|
FValueBuf: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
FValueStart,
|
|
|
|
FValuePtr,
|
2013-05-31 16:03:11 +06:00
|
|
|
FValueEnd: PChar;
|
2010-11-06 22:16:58 +02:00
|
|
|
public
|
|
|
|
constructor Create;
|
|
|
|
procedure Clear;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure AppendChar(aChar: Char);
|
|
|
|
procedure AppendText(aText: PChar; aCount: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
function Length: Integer;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
property ValueStart: PChar read FValueStart;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlSource = class
|
|
|
|
private
|
2010-11-06 22:21:34 +02:00
|
|
|
FPrevChar: Char;
|
|
|
|
FCurLine, FCurPos: Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
FTokenStack: array of TXmlToken;
|
|
|
|
FTokenStackTop: Integer;
|
|
|
|
FToken: TXmlToken;
|
2013-05-31 16:03:11 +06:00
|
|
|
function ExpectQuotedText(aQuote: Char): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
public
|
2013-05-31 16:03:11 +06:00
|
|
|
CurChar: Char;
|
2010-11-06 22:16:58 +02:00
|
|
|
constructor Create;
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
function EOF: Boolean; virtual; abstract;
|
2010-11-06 22:21:34 +02:00
|
|
|
function DoNext: Boolean; virtual; abstract;
|
|
|
|
function Next: Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure SkipBlanks;
|
2013-05-31 16:03:11 +06:00
|
|
|
function ExpectXmlName: String;
|
|
|
|
function ExpectXmlEntity: Char;
|
|
|
|
procedure ExpectChar(aChar: Char);
|
|
|
|
procedure ExpectText(aText: PChar);
|
2010-11-06 22:16:58 +02:00
|
|
|
function ExpectDecimalInteger: Integer;
|
|
|
|
function ExpectHexInteger: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
function ParseTo(aText: PChar): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure ParseAttrs(aNode: TXmlNode);
|
|
|
|
|
|
|
|
procedure NewToken;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure AppendTokenChar(aChar: Char);
|
|
|
|
procedure AppendTokenText(aText: PChar; aCount: Integer);
|
|
|
|
function AcceptToken: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure DropToken;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
TStringXmlSource = class(TXmlSource)
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
2013-05-31 16:03:11 +06:00
|
|
|
FSource: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
FSourcePtr,
|
2013-05-31 16:03:11 +06:00
|
|
|
FSourceEnd: PChar;
|
2010-11-06 22:16:58 +02:00
|
|
|
public
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor Create(const aSource: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
function EOF: Boolean; override;
|
2010-11-06 22:21:34 +02:00
|
|
|
function DoNext: Boolean; override;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
TAnsiStreamXmlSource = class(TXmlSource)
|
2010-11-06 22:16:58 +02:00
|
|
|
private
|
|
|
|
FStream: TStream;
|
|
|
|
FBufStart,
|
|
|
|
FBufPtr,
|
2013-05-31 16:03:11 +06:00
|
|
|
FBufEnd: PAnsiChar;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
FBufSize: Integer;
|
|
|
|
FSize: Integer;
|
|
|
|
public
|
|
|
|
constructor Create(aStream: TStream; aBufSize: Integer);
|
|
|
|
function EOF: Boolean; override;
|
2010-11-06 22:21:34 +02:00
|
|
|
function DoNext: Boolean; override;
|
2010-11-06 22:16:58 +02:00
|
|
|
destructor Destroy; override;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlNodeList = class(TXmlBase, IXmlNodeList)
|
|
|
|
private
|
|
|
|
FOwnerNode: TXmlNode;
|
|
|
|
|
|
|
|
FItems: array of TXmlNode;
|
|
|
|
FCount: Integer;
|
|
|
|
procedure Grow;
|
|
|
|
protected
|
|
|
|
function Get_Count: Integer;
|
|
|
|
function Get_Item(anIndex: Integer): IXmlNode;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_XML: String;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
public
|
|
|
|
constructor Create(anOwnerNode: TXmlNode);
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function IndexOfNode(aNode: TXmlNode): Integer;
|
|
|
|
procedure ParseXML(anXml: TXmlSource; aNames: TXmlNameTable; aPreserveWhiteSpace: Boolean);
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure SortElements(aCompare: TXmlCompareNodes);
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure LoadBinXml(aReader: TBinaryXmlReader; aCount: Integer; aNames: TXmlNameTable);
|
|
|
|
procedure SaveBinXml(aWriter: TBinaryXmlWriter);
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure InsertNode(aNode: TXmlNode; anIndex: Integer);
|
|
|
|
function RemoveNode(aNode: TXmlNode): Integer;
|
|
|
|
procedure DeleteNode(anIndex: Integer);
|
|
|
|
procedure ReplaceNode(anIndex: Integer; aNode: TXmlNode);
|
|
|
|
procedure ClearNodes;
|
|
|
|
|
|
|
|
function IndexOf(const aNode: IXmlNode): Integer;
|
|
|
|
procedure Insert(const aNode: IXmlNode; anIndex: Integer);
|
|
|
|
function Remove(const aNode: IXmlNode): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure Delete(anIndex: Integer);
|
|
|
|
procedure Clear;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure Add(const aNode: IXmlNode);
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
PXmlAttrData = ^TXmlAttrData;
|
|
|
|
TXmlAttrData = record
|
|
|
|
NameID: Integer;
|
|
|
|
Value: Variant;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlDocument = class;
|
|
|
|
TXmlNode = class(TXmlBase, IXmlNode)
|
|
|
|
private
|
2010-11-06 22:21:34 +02:00
|
|
|
FSourceLine, FSourceCol: Integer;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
FParentNode: TXmlNode;
|
|
|
|
// FNames - ������� ����. �������� �����
|
|
|
|
FNames: TXmlNameTable;
|
|
|
|
// ���������� ��������� � ������� FAttrs
|
|
|
|
FAttrCount: Integer;
|
|
|
|
// ������ ���������
|
|
|
|
FAttrs: array of TXmlAttrData;
|
|
|
|
// ������ �������� �����
|
|
|
|
FChilds: TXmlNodeList;
|
|
|
|
function GetChilds: TXmlNodeList; virtual;
|
|
|
|
function FindFirstChild(aNameID: Integer): TXmlNode;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure GetAttrsXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
function FindAttrData(aNameID: Integer): PXmlAttrData;
|
|
|
|
function GetOwnerDocument: TXmlDocument;
|
|
|
|
procedure SetNameTable(aValue: TXmlNameTable; aMap: TList);
|
|
|
|
procedure SetNodeNameID(aValue: Integer); virtual;
|
2010-11-06 22:21:34 +02:00
|
|
|
function DoCloneNode(aDeep: Boolean): IXmlNode; virtual; abstract;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
protected
|
|
|
|
// IXmlNode
|
2010-11-06 22:21:34 +02:00
|
|
|
function Get_SourceLine: Integer;
|
|
|
|
function Get_SourceCol: Integer;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function Get_NameTable: IXmlNameTable;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_NodeName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function Get_NodeNameID: Integer; virtual; abstract;
|
|
|
|
function Get_NodeType: Integer; virtual; abstract;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Text: String; virtual; abstract;
|
|
|
|
procedure Set_Text(const aValue: String); virtual; abstract;
|
2010-11-06 22:16:58 +02:00
|
|
|
function CloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure LoadBinXml(aReader: TBinaryXmlReader);
|
|
|
|
procedure SaveBinXml(aWriter: TBinaryXmlWriter);
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function Get_DataType: Integer; virtual;
|
|
|
|
function Get_TypedValue: Variant; virtual;
|
|
|
|
procedure Set_TypedValue(const aValue: Variant); virtual;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure GetXML(var anXml: TStringBuilder); virtual; abstract;
|
|
|
|
function Get_XML: String; virtual;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function Get_OwnerDocument: IXmlDocument; virtual;
|
|
|
|
function Get_ParentNode: IXmlNode;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_NextSibling: IXmlNode;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function Get_ChildNodes: IXmlNodeList; virtual;
|
|
|
|
procedure AppendChild(const aChild: IXmlNode);
|
|
|
|
|
|
|
|
function AppendElement(aNameID: Integer): IXmlElement; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function AppendElement(const aName: String): IXmlElement; overload;
|
|
|
|
function AppendText(const aData: String): IXmlText;
|
|
|
|
function AppendCDATA(const aData: String): IXmlCDATASection;
|
|
|
|
function AppendComment(const aData: String): IXmlComment;
|
2010-11-06 22:16:58 +02:00
|
|
|
function AppendProcessingInstruction(aTargetID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String): IXmlProcessingInstruction; overload;
|
|
|
|
function AppendProcessingInstruction(const aTarget: String;
|
|
|
|
const aData: String): IXmlProcessingInstruction; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure InsertBefore(const aChild, aBefore: IXmlNode);
|
|
|
|
procedure ReplaceChild(const aNewChild, anOldChild: IXmlNode);
|
|
|
|
procedure RemoveChild(const aChild: IXmlNode);
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetChildText(const aName: String; const aDefault: String = ''): String; overload;
|
|
|
|
function GetChildText(aNameID: Integer; const aDefault: String = ''): String; overload;
|
|
|
|
procedure SetChildText(const aName, aValue: String); overload;
|
|
|
|
procedure SetChildText(aNameID: Integer; const aValue: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function NeedChild(aNameID: Integer): IXmlNode; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedChild(const aName: String): IXmlNode; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function EnsureChild(aNameID: Integer): IXmlNode; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function EnsureChild(const aName: String): IXmlNode; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure RemoveAllChilds;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function SelectNodes(const anExpression: String): IXmlNodeList; overload;
|
2010-11-06 22:21:34 +02:00
|
|
|
function SelectNodes(aNodeNameID: Integer): IXmlNodeList; overload;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function SelectSingleNode(const anExpression: String): IXmlNode;
|
2010-11-06 22:16:58 +02:00
|
|
|
function FindElement(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlElement;
|
2010-11-06 22:21:34 +02:00
|
|
|
function FindElements(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlNodeList;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function Get_AttrCount: Integer;
|
|
|
|
function Get_AttrNameID(anIndex: Integer): Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_AttrName(anIndex: Integer): String;
|
|
|
|
procedure RemoveAttr(const aName: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure RemoveAttr(aNameID: Integer); overload;
|
|
|
|
procedure RemoveAllAttrs;
|
|
|
|
|
|
|
|
function AttrExists(aNameID: Integer): Boolean; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function AttrExists(const aName: String): Boolean; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function GetAttrType(aNameID: Integer): Integer; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetAttrType(const aName: String): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function GetVarAttr(aNameID: Integer; const aDefault: Variant): Variant; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetVarAttr(const aName: String; const aDefault: Variant): Variant; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetVarAttr(aNameID: Integer; const aValue: Variant); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetVarAttr(const aName: String; aValue: Variant); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function NeedVarAttr(aNameID: Integer): Variant; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedVarAttr(const aName: String): Variant; overload;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedAttr(aNameID: Integer): String; overload;
|
|
|
|
function NeedAttr(const aName: String): String; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetAttr(aNameID: Integer; const aDefault: String = ''): String; overload;
|
|
|
|
function GetAttr(const aName: String; const aDefault: String = ''): String; overload;
|
|
|
|
procedure SetAttr(aNameID: Integer; const aValue: String); overload;
|
|
|
|
procedure SetAttr(const aName, aValue: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function GetBoolAttr(aNameID: Integer; aDefault: Boolean = False): Boolean; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetBoolAttr(const aName: String; aDefault: Boolean = False): Boolean; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetBoolAttr(aNameID: Integer; aValue: Boolean = False); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetBoolAttr(const aName: String; aValue: Boolean); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function GetIntAttr(aNameID: Integer; aDefault: Integer = 0): Integer; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetIntAttr(const aName: String; aDefault: Integer = 0): Integer; overload;
|
|
|
|
function NeedIntAttr(const aName: String): Integer; overload;
|
|
|
|
function NeedIntAttr(aNameID: Integer): Integer; overload;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetIntAttr(aNameID: Integer; aValue: Integer); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetIntAttr(const aName: String; aValue: Integer); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function GetDateTimeAttr(aNameID: Integer; aDefault: TDateTime = 0): TDateTime; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetDateTimeAttr(const aName: String; aDefault: TDateTime = 0): TDateTime; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetDateTimeAttr(aNameID: Integer; aValue: TDateTime); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetDateTimeAttr(const aName: String; aValue: TDateTime); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function GetFloatAttr(aNameID: Integer; aDefault: Double = 0): Double; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetFloatAttr(const aName: String; aDefault: Double = 0): Double; overload;
|
2010-11-06 22:21:34 +02:00
|
|
|
function NeedFloatAttr(aNameID: Integer): Double; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function NeedFloatAttr(const aName: String): Double; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetFloatAttr(aNameID: Integer; aValue: Double); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetFloatAttr(const aName: String; aValue: Double); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetHexAttr(const aName: String; aDefault: Integer = 0): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function GetHexAttr(aNameID: Integer; aDefault: Integer = 0): Integer; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SetHexAttr(const aName: String; aValue: Integer; aDigits: Integer = 8); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure SetHexAttr(aNameID: Integer; aValue: Integer; aDigits: Integer = 8); overload;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetEnumAttr(const aName: String;
|
|
|
|
const aValues: array of String; aDefault: Integer = 0): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function GetEnumAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aValues: array of String; aDefault: Integer = 0): Integer; overload;
|
|
|
|
function NeedEnumAttr(const aName: String;
|
|
|
|
const aValues: array of String): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function NeedEnumAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aValues: array of String): Integer; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure RemoveTextNodes;
|
|
|
|
procedure ReplaceTextByCDATASection(const aText: String);
|
|
|
|
procedure ReplaceTextByBinaryData(const aData; aSize: Integer;
|
2010-11-06 22:21:34 +02:00
|
|
|
aMaxLineLength: Integer);
|
2013-05-31 16:03:11 +06:00
|
|
|
function GetTextAsBinaryData: RawByteString;
|
|
|
|
function GetOwnText: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function Get_Values(const aName: String): Variant;
|
|
|
|
procedure Set_Values(const aName: String; const aValue: Variant);
|
|
|
|
|
|
|
|
function AsElement: IXmlElement; virtual;
|
|
|
|
function AsText: IXmlText; virtual;
|
|
|
|
function AsCDATASection: IXmlCDATASection; virtual;
|
|
|
|
function AsComment: IXmlComment; virtual;
|
2010-11-06 22:21:34 +02:00
|
|
|
function AsProcessingInstruction: IXmlProcessingInstruction; virtual;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
public
|
|
|
|
constructor Create(aNames: TXmlNameTable);
|
|
|
|
destructor Destroy; override;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlElement = class(TXmlNode, IXmlElement)
|
|
|
|
private
|
|
|
|
FNameID: Integer;
|
|
|
|
FData: Variant;
|
|
|
|
procedure SetNodeNameID(aValue: Integer); override;
|
|
|
|
function DoCloneNode(aDeep: Boolean): IXmlNode; override;
|
|
|
|
protected
|
|
|
|
function GetChilds: TXmlNodeList; override;
|
|
|
|
|
|
|
|
function Get_NodeNameID: Integer; override;
|
|
|
|
function Get_NodeType: Integer; override;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Text: String; override;
|
|
|
|
procedure Set_Text(const aValue: String); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function Get_DataType: Integer; override;
|
|
|
|
function Get_TypedValue: Variant; override;
|
|
|
|
procedure Set_TypedValue(const aValue: Variant); override;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure GetXML(var anXml: TStringBuilder); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function AsElement: IXmlElement; override;
|
|
|
|
function Get_ChildNodes: IXmlNodeList; override;
|
|
|
|
|
|
|
|
public
|
|
|
|
constructor Create(aNames: TXmlNameTable; aNameID: Integer);
|
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlCharacterData = class(TXmlNode, IXmlCharacterData)
|
|
|
|
private
|
2013-05-31 16:03:11 +06:00
|
|
|
FData: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
protected
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Text: String; override;
|
|
|
|
procedure Set_Text(const aValue: String); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
public
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor Create(aNames: TXmlNameTable; const aData: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlText = class(TXmlNode, IXmlText)
|
|
|
|
private
|
|
|
|
FData: Variant;
|
|
|
|
function DoCloneNode(aDeep: Boolean): IXmlNode; override;
|
|
|
|
protected
|
|
|
|
function Get_NodeNameID: Integer; override;
|
|
|
|
function Get_NodeType: Integer; override;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Text: String; override;
|
|
|
|
procedure Set_Text(const aValue: String); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function Get_DataType: Integer; override;
|
|
|
|
function Get_TypedValue: Variant; override;
|
|
|
|
procedure Set_TypedValue(const aValue: Variant); override;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure GetXML(var anXml: TStringBuilder); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function AsText: IXmlText; override;
|
|
|
|
public
|
|
|
|
constructor Create(aNames: TXmlNameTable; const aData: Variant);
|
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlCDATASection = class(TXmlCharacterData, IXmlCDATASection)
|
|
|
|
protected
|
|
|
|
function Get_NodeNameID: Integer; override;
|
|
|
|
function Get_NodeType: Integer; override;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure GetXML(var anXml: TStringBuilder); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function AsCDATASection: IXmlCDATASection; override;
|
|
|
|
function DoCloneNode(aDeep: Boolean): IXmlNode; override;
|
|
|
|
public
|
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlComment = class(TXmlCharacterData, IXmlComment)
|
|
|
|
protected
|
|
|
|
function Get_NodeNameID: Integer; override;
|
|
|
|
function Get_NodeType: Integer; override;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure GetXML(var anXml: TStringBuilder); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function AsComment: IXmlComment; override;
|
|
|
|
function DoCloneNode(aDeep: Boolean): IXmlNode; override;
|
|
|
|
public
|
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlProcessingInstruction = class(TXmlNode, IXmlProcessingInstruction)
|
|
|
|
private
|
|
|
|
FTargetID: Integer;
|
|
|
|
FData: String;
|
|
|
|
procedure SetNodeNameID(aValue: Integer); override;
|
|
|
|
function DoCloneNode(aDeep: Boolean): IXmlNode; override;
|
|
|
|
protected
|
|
|
|
function Get_NodeNameID: Integer; override;
|
|
|
|
function Get_NodeType: Integer; override;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Text: String; override;
|
|
|
|
procedure Set_Text(const aText: String); override;
|
|
|
|
procedure GetXML(var anXml: TStringBuilder); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function AsProcessingInstruction: IXmlProcessingInstruction; override;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Target: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
public
|
|
|
|
constructor Create(aNames: TXmlNameTable; aTargetID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
TXmlDocument = class(TXmlNode, IXmlDocument)
|
|
|
|
private
|
|
|
|
FPreserveWhiteSpace: Boolean;
|
|
|
|
|
|
|
|
function DoCloneNode(aDeep: Boolean): IXmlNode; override;
|
|
|
|
protected
|
|
|
|
function Get_NodeNameID: Integer; override;
|
|
|
|
function Get_NodeType: Integer; override;
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_Text: String; override;
|
|
|
|
procedure Set_Text(const aText: String); override;
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure GetXML(var anXml: TStringBuilder); override;
|
2010-11-06 22:16:58 +02:00
|
|
|
function Get_PreserveWhiteSpace: Boolean;
|
|
|
|
procedure Set_PreserveWhiteSpace(aValue: Boolean);
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function NewDocument(const aVersion, anEncoding: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aRootElementNameID: Integer): IXmlElement; overload;
|
|
|
|
function NewDocument(const aVersion, anEncoding,
|
2013-05-31 16:03:11 +06:00
|
|
|
aRootElementName: String): IXmlElement; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
function CreateElement(aNameID: Integer): IXmlElement; overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
function CreateElement(const aName: String): IXmlElement; overload;
|
|
|
|
function CreateText(const aData: String): IXmlText;
|
|
|
|
function CreateCDATASection(const aData: String): IXmlCDATASection;
|
|
|
|
function CreateComment(const aData: String): IXmlComment;
|
2010-11-06 22:16:58 +02:00
|
|
|
function Get_DocumentElement: IXmlElement;
|
|
|
|
function CreateProcessingInstruction(const aTarget,
|
2013-05-31 16:03:11 +06:00
|
|
|
aData: String): IXmlProcessingInstruction; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
function CreateProcessingInstruction(aTargetID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String): IXmlProcessingInstruction; overload;
|
|
|
|
procedure LoadXML(const anXml: String); overload;
|
|
|
|
procedure LoadXML(const anXml: RawByteString); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure Load(aStream: TStream); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure Load(const aFileName: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure LoadResource(aType, aName: PChar);
|
|
|
|
|
|
|
|
procedure Save(aStream: TStream); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure Save(const aFileName: String); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
procedure SaveBinary(aStream: TStream; anOptions: LongWord); overload;
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure SaveBinary(const aFileName: String; anOptions: LongWord); overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function Get_BinaryXML: RawByteString;
|
|
|
|
procedure LoadBinaryXML(const anXml: RawByteString);
|
2010-11-06 22:16:58 +02:00
|
|
|
public
|
|
|
|
constructor Create(aNames: TXmlNameTable);
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlNodeList }
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlNodeList.ClearNodes;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aNode: TXmlNode;
|
|
|
|
begin
|
|
|
|
for i := 0 to FCount - 1 do begin
|
|
|
|
aNode := FItems[i];
|
2013-05-31 16:03:11 +06:00
|
|
|
if Assigned(FOwnerNode) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode.FParentNode := nil;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode._Release;
|
|
|
|
end;
|
|
|
|
FCount := 0;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlNodeList.DeleteNode(anIndex: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aNode: TXmlNode;
|
|
|
|
begin
|
|
|
|
aNode := FItems[anIndex];
|
|
|
|
Dec(FCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
if anIndex < FCount then begin
|
|
|
|
Move(FItems[anIndex + 1], FItems[anIndex], (FCount - anIndex)*SizeOf(TXmlNode));
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
if Assigned(aNode) then begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if Assigned(FOwnerNode) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode.FParentNode := nil;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode._Release;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TXmlNodeList.Create(anOwnerNode: TXmlNode);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FOwnerNode := anOwnerNode;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TXmlNodeList.Destroy;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
ClearNodes;
|
2010-11-06 22:16:58 +02:00
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNodeList.Get_Item(anIndex: Integer): IXmlNode;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if (anIndex < 0) or (anIndex >= FCount) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
raise Exception.Create(SSimpleXmlError1);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := FItems[anIndex]
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNodeList.Get_Count: Integer;
|
|
|
|
begin
|
|
|
|
Result := FCount
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlNodeList.IndexOfNode(aNode: TXmlNode): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to FCount - 1 do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
if FItems[i] = aNode then begin
|
|
|
|
Result := i;
|
|
|
|
Exit
|
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := -1;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNodeList.Grow;
|
|
|
|
var
|
|
|
|
aDelta: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if Length(FItems) > 64 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aDelta := Length(FItems) div 4
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if Length(FItems) > 8 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aDelta := 16
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aDelta := 4;
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
SetLength(FItems, Length(FItems) + aDelta);
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlNodeList.InsertNode(aNode: TXmlNode; anIndex: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if anIndex = -1 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
anIndex := FCount;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
if FCount = Length(FItems) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Grow;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
if anIndex < FCount then begin
|
|
|
|
Move(FItems[anIndex], FItems[anIndex + 1], (FCount - anIndex)*SizeOf(TXmlNode));
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
FItems[anIndex] := aNode;
|
|
|
|
Inc(FCount);
|
|
|
|
if aNode <> nil then begin
|
|
|
|
aNode._AddRef;
|
|
|
|
if Assigned(FOwnerNode) then begin
|
|
|
|
aNode.FParentNode := FOwnerNode;
|
|
|
|
aNode.SetNameTable(FOwnerNode.FNames, nil);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlNodeList.RemoveNode(aNode: TXmlNode): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
Result := IndexOfNode(aNode);
|
2013-05-31 16:03:11 +06:00
|
|
|
if Result <> -1 then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
DeleteNode(Result);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlNodeList.ReplaceNode(anIndex: Integer; aNode: TXmlNode);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
anOldNode: TXmlNode;
|
|
|
|
begin
|
|
|
|
anOldNode := FItems[anIndex];
|
2013-05-31 16:03:11 +06:00
|
|
|
if aNode = anOldNode then begin
|
|
|
|
exit
|
|
|
|
end;
|
|
|
|
if Assigned(anOldNode) then begin
|
|
|
|
if Assigned(FOwnerNode) then begin
|
|
|
|
anOldNode.FParentNode := nil;
|
|
|
|
end;
|
|
|
|
anOldNode._Release;
|
|
|
|
end;
|
|
|
|
FItems[anIndex] := aNode;
|
|
|
|
if Assigned(aNode) then begin
|
|
|
|
aNode._AddRef;
|
|
|
|
if Assigned(FOwnerNode) then begin
|
|
|
|
aNode.FParentNode := FOwnerNode;
|
|
|
|
aNode.SetNameTable(FOwnerNode.FNames, nil);
|
|
|
|
end
|
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNodeList.Get_XML: String;
|
2010-11-06 22:21:34 +02:00
|
|
|
var
|
|
|
|
anXml: TStringBuilder;
|
|
|
|
begin
|
|
|
|
anXml.Init;
|
|
|
|
GetXML(anXml);
|
|
|
|
anXml.GetString(Result);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNodeList.GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to FCount - 1 do begin
|
2010-11-06 22:21:34 +02:00
|
|
|
FItems[i].GetXML(anXml);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlNodeList.ParseXML(anXml: TXmlSource; aNames: TXmlNameTable; aPreserveWhiteSpace: Boolean);
|
|
|
|
var
|
|
|
|
aLine, aCol: Integer;
|
|
|
|
|
|
|
|
procedure DoAppend(aNode: TXmlNode);
|
|
|
|
begin
|
|
|
|
aNode.FSourceLine := aLine;
|
|
|
|
aNode.FSourceCol := aCol;
|
|
|
|
InsertNode(aNode, -1);
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// �� �����: ������ ������
|
|
|
|
// �� ������: ������ �������� '<'
|
|
|
|
procedure ParseText;
|
|
|
|
var
|
|
|
|
aText: String;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.NewToken;
|
2013-05-31 16:03:11 +06:00
|
|
|
while not anXml.EOF and (anXml.CurChar <> '<') do begin
|
|
|
|
if anXml.CurChar = '&' then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.AppendTokenChar(anXml.ExpectXmlEntity)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.AppendTokenChar(anXml.CurChar);
|
|
|
|
anXml.Next;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:21:34 +02:00
|
|
|
aText := anXml.AcceptToken;
|
2013-05-31 16:03:11 +06:00
|
|
|
if aPreserveWhiteSpace or (Trim(aText) <> '') then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
DoAppend(TXmlText.Create(aNames, aText));
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
// CurChar - '?'
|
|
|
|
procedure ParseProcessingInstruction;
|
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aTarget: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode: TXmlProcessingInstruction;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Next;
|
|
|
|
aTarget := anXml.ExpectXmlName;
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode := TXmlProcessingInstruction.Create(aNames, aNames.GetID(aTarget), '');
|
2010-11-06 22:21:34 +02:00
|
|
|
DoAppend(aNode);
|
2010-11-06 22:16:58 +02:00
|
|
|
if aNode.FTargetID = aNames.FXmlID then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.ParseAttrs(aNode);
|
|
|
|
anXml.ExpectText('?>');
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
2013-05-31 16:03:11 +06:00
|
|
|
else begin
|
2010-11-06 22:21:34 +02:00
|
|
|
aNode.FData := anXml.ParseTo('?>');
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
// �� �����: ������ '--'
|
|
|
|
// �� ������: ������ ����� '-->'
|
|
|
|
procedure ParseComment;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.ExpectText('--');
|
|
|
|
DoAppend(TXmlComment.Create(aNames, anXml.ParseTo('-->')));
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
// �� �����: '[CDATA['
|
|
|
|
// �� ������: ������ ����� ']]>'
|
|
|
|
procedure ParseCDATA;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.ExpectText('[CDATA[');
|
|
|
|
DoAppend(TXmlCDATASection.Create(aNames, anXml.ParseTo(']]>')));
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// �� �����: 'DOCTYPE'
|
|
|
|
// �� ������: ������ ����� '>'
|
|
|
|
procedure ParseDOCTYPE;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.ExpectText('DOCTYPE');
|
|
|
|
anXml.ParseTo('>');
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
// �� �����: '���-��������'
|
|
|
|
// �� ������: ������ ����� '>'
|
|
|
|
procedure ParseElement;
|
|
|
|
var
|
|
|
|
aNameID: Integer;
|
|
|
|
aNode: TXmlElement;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
aNameID := aNames.GetID(anXml.ExpectXmlName);
|
2013-05-31 16:03:11 +06:00
|
|
|
if anXml.EOF then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
raise Exception.Create(SSimpleXMLError2);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
if not ((anXml.CurChar <= ' ') or (anXml.CurChar = '/') or (anXml.CurChar = '>')) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
raise Exception.Create(SSimpleXMLError3);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode := TXmlElement.Create(aNames, aNameID);
|
2010-11-06 22:21:34 +02:00
|
|
|
DoAppend(aNode);
|
|
|
|
anXml.ParseAttrs(aNode);
|
2013-05-31 16:03:11 +06:00
|
|
|
if anXml.CurChar = '/' then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.ExpectText('/>')
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.ExpectChar('>');
|
|
|
|
aNode.GetChilds.ParseXML(anXml, aNames, aPreserveWhiteSpace);
|
|
|
|
anXml.ExpectChar('/');
|
2013-05-31 16:03:11 +06:00
|
|
|
anXml.ExpectText(PChar(aNames.GetName(aNameID)));
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.SkipBlanks;
|
|
|
|
anXml.ExpectChar('>');
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
while not anXml.EOF do begin
|
|
|
|
aLine := anXml.FCurLine;
|
|
|
|
aCol := anXml.FCurPos;
|
2010-11-06 22:16:58 +02:00
|
|
|
ParseText;
|
2010-11-06 22:21:34 +02:00
|
|
|
aLine := anXml.FCurLine;
|
|
|
|
aCol := anXml.FCurPos;
|
2013-05-31 16:03:11 +06:00
|
|
|
if anXml.CurChar = '<' then begin // ������ ��������
|
|
|
|
if anXml.Next then begin
|
|
|
|
if anXml.CurChar = '/' then begin // ����������� ��� ��������
|
2010-11-06 22:16:58 +02:00
|
|
|
Exit
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if anXml.CurChar = '?' then begin // ����������
|
2010-11-06 22:16:58 +02:00
|
|
|
ParseProcessingInstruction
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:21:34 +02:00
|
|
|
else if anXml.CurChar = '!' then begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if anXml.Next then begin
|
|
|
|
if anXml.CurChar = '-' then begin // ����������
|
2010-11-06 22:16:58 +02:00
|
|
|
ParseComment
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if anXml.CurChar = '[' then begin // ������ CDATA
|
2010-11-06 22:16:58 +02:00
|
|
|
ParseCDATA
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
ParseDOCTYPE
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
2013-05-31 16:03:11 +06:00
|
|
|
else begin // ����������� ��� ��������
|
2010-11-06 22:16:58 +02:00
|
|
|
ParseElement
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNodeList.LoadBinXml(aReader: TBinaryXmlReader;
|
2010-11-06 22:16:58 +02:00
|
|
|
aCount: Integer; aNames: TXmlNameTable);
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aNodeType: Byte;
|
|
|
|
aNode: TXmlNode;
|
|
|
|
aNameID: LongInt;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
ClearNodes;
|
2010-11-06 22:16:58 +02:00
|
|
|
SetLength(FItems, aCount);
|
|
|
|
for i := 0 to aCount - 1 do begin
|
|
|
|
aReader.Read(aNodeType, sizeof(aNodeType));
|
|
|
|
case aNodeType of
|
2013-05-31 16:03:11 +06:00
|
|
|
NODE_ELEMENT: begin
|
|
|
|
aNameID := aReader.ReadLongint;
|
|
|
|
aNode := TXmlElement.Create(aNames, aNameID);
|
|
|
|
InsertNode(aNode, -1);
|
|
|
|
aReader.ReadVariant(TVarData(TXmlElement(aNode).FData));
|
|
|
|
aNode.LoadBinXml(aReader);
|
|
|
|
end;
|
|
|
|
NODE_TEXT: begin
|
|
|
|
aNode := TXmlText.Create(aNames, Unassigned);
|
|
|
|
InsertNode(aNode, -1);
|
|
|
|
aReader.ReadVariant(TVarData(TXmlText(aNode).FData));
|
|
|
|
end;
|
|
|
|
NODE_CDATA_SECTION: begin
|
2010-11-06 22:21:34 +02:00
|
|
|
InsertNode(TXmlCDATASection.Create(aNames, aReader.ReadXmlString), -1);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
NODE_PROCESSING_INSTRUCTION: begin
|
|
|
|
aNameID := aReader.ReadLongint;
|
|
|
|
aNode := TXmlProcessingInstruction.Create(aNames, aNameID,
|
|
|
|
aReader.ReadXmlString);
|
|
|
|
InsertNode(aNode, -1);
|
|
|
|
aNode.LoadBinXml(aReader);
|
|
|
|
end;
|
|
|
|
NODE_COMMENT: begin
|
2010-11-06 22:21:34 +02:00
|
|
|
InsertNode(TXmlComment.Create(aNames, aReader.ReadXmlString), -1);
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
raise Exception.Create(SSimpleXMLError4);
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNodeList.SaveBinXml(aWriter: TBinaryXmlWriter);
|
2010-11-06 22:16:58 +02:00
|
|
|
const
|
|
|
|
EmptyVar: TVarData = (VType:varEmpty);
|
|
|
|
var
|
|
|
|
aCount: LongInt;
|
|
|
|
i: Integer;
|
|
|
|
aNodeType: Byte;
|
|
|
|
aNode: TXmlNode;
|
|
|
|
begin
|
|
|
|
aCount := FCount;
|
|
|
|
for i := 0 to aCount - 1 do begin
|
|
|
|
aNode := FItems[i];
|
|
|
|
aNodeType := aNode.Get_NodeType;
|
|
|
|
aWriter.Write(aNodeType, sizeof(aNodeType));
|
|
|
|
case aNodeType of
|
|
|
|
NODE_ELEMENT:
|
|
|
|
with TXmlElement(aNode) do begin
|
|
|
|
aWriter.WriteLongint(FNameID);
|
|
|
|
if Assigned(FChilds) and (FChilds.FCount > 0) or VarIsEmpty(FData) then
|
|
|
|
aWriter.WriteVariant(EmptyVar)
|
|
|
|
else
|
|
|
|
aWriter.WriteVariant(TVarData(FData));
|
|
|
|
SaveBinXml(aWriter);
|
|
|
|
end;
|
|
|
|
NODE_TEXT:
|
|
|
|
aWriter.WriteVariant(TVarData(TXmlText(aNode).FData));
|
|
|
|
NODE_CDATA_SECTION:
|
|
|
|
aWriter.WriteXmlString(TXmlCDATASection(aNode).FData);
|
|
|
|
NODE_PROCESSING_INSTRUCTION:
|
|
|
|
begin
|
|
|
|
aWriter.WriteLongint(TXmlProcessingInstruction(aNode).FTargetID);
|
|
|
|
aWriter.WriteXmlString(TXmlProcessingInstruction(aNode).FData);
|
|
|
|
aNode.SaveBinXml(aWriter);
|
|
|
|
end;
|
|
|
|
NODE_COMMENT:
|
|
|
|
aWriter.WriteXmlString(TXmlComment(aNode).FData);
|
|
|
|
else
|
|
|
|
raise Exception.Create(SSimpleXmlError5);
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure QuickSortNodes(aList: TXmlNodeList; L, R: Integer;
|
|
|
|
aCompare: TXmlCompareNodes);
|
|
|
|
var
|
|
|
|
I, J: Integer;
|
|
|
|
P, T: TXmlNode;
|
|
|
|
begin
|
|
|
|
repeat
|
|
|
|
I := L;
|
|
|
|
J := R;
|
|
|
|
P := aList.FItems[(L + R) shr 1];
|
|
|
|
repeat
|
|
|
|
while aCompare(aList.FItems[I], P) < 0 do
|
|
|
|
Inc(I);
|
|
|
|
while aCompare(aList.FItems[J], P) > 0 do
|
|
|
|
Dec(J);
|
|
|
|
if I <= J then
|
|
|
|
begin
|
|
|
|
T := aList.FItems[I];
|
|
|
|
aList.FItems[I] := aList.FItems[J];
|
|
|
|
aList.FItems[J] := T;
|
|
|
|
Inc(I);
|
|
|
|
Dec(J);
|
|
|
|
end;
|
|
|
|
until I > J;
|
|
|
|
if L < J then
|
|
|
|
QuickSortNodes(aList, L, J, aCompare);
|
|
|
|
L := I;
|
|
|
|
until I >= R;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNodeList.SortElements(aCompare: TXmlCompareNodes);
|
|
|
|
begin
|
|
|
|
if FCount > 0 then
|
|
|
|
QuickSortNodes(Self, 0, FCount - 1, aCompare);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNodeList.Clear;
|
|
|
|
begin
|
|
|
|
ClearNodes;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNodeList.Delete(anIndex: Integer);
|
|
|
|
begin
|
|
|
|
DeleteNode(anIndex);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNodeList.IndexOf(const aNode: IXmlNode): Integer;
|
|
|
|
begin
|
|
|
|
Result := IndexOfNode(aNode.GetObject as TXmlNode);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNodeList.Insert(const aNode: IXmlNode; anIndex: Integer);
|
|
|
|
begin
|
|
|
|
InsertNode(aNode.GetObject as TXmlNode, anIndex);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNodeList.Remove(const aNode: IXmlNode): Integer;
|
|
|
|
begin
|
|
|
|
Result := RemoveNode(aNode.GetObject as TXmlNode)
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNodeList.Add(const aNode: IXmlNode);
|
|
|
|
begin
|
|
|
|
Insert(aNode.GetObject as TXmlNode, -1);
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
{ TXmlNode }
|
|
|
|
|
|
|
|
constructor TXmlNode.Create(aNames: TXmlNameTable);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FNames := aNames;
|
|
|
|
FNames._AddRef;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TXmlNode.Destroy;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
if Assigned(FChilds) then
|
2010-11-06 22:16:58 +02:00
|
|
|
FChilds._Release;
|
|
|
|
FNames._Release;
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetChilds: TXmlNodeList;
|
|
|
|
begin
|
|
|
|
if not Assigned(FChilds) then begin
|
|
|
|
FChilds := TXmlNodeList.Create(Self);
|
|
|
|
FChilds._AddRef;
|
|
|
|
end;
|
|
|
|
Result := FChilds;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.AppendChild(const aChild: IXmlNode);
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild.GetObject as TXmlNode, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_AttrCount: Integer;
|
|
|
|
begin
|
|
|
|
Result := FAttrCount;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.Get_AttrName(anIndex: Integer): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := FNames.GetName(FAttrs[anIndex].NameID);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_AttrNameID(anIndex: Integer): Integer;
|
|
|
|
begin
|
|
|
|
Result := FAttrs[anIndex].NameID;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_ChildNodes: IXmlNodeList;
|
|
|
|
begin
|
|
|
|
Result := GetChilds
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_NameTable: IXmlNameTable;
|
|
|
|
begin
|
|
|
|
Result := FNames
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetAttr(const aName, aDefault: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := GetAttr(FNames.GetID(aName), aDefault)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aDefault: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aData: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
aData := FindAttrData(aNameID);
|
2013-05-31 16:03:11 +06:00
|
|
|
if Assigned(aData) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aData.Value
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aDefault
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetBoolAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
aDefault: Boolean): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aData: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
aData := FindAttrData(aNameID);
|
|
|
|
if Assigned(aData) then
|
|
|
|
Result := aData.Value
|
|
|
|
else
|
|
|
|
Result := aDefault
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetBoolAttr(const aName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aDefault: Boolean): Boolean;
|
|
|
|
begin
|
|
|
|
Result := GetBoolAttr(FNames.GetID(aName), aDefault)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.FindFirstChild(aNameID: Integer): TXmlNode;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
if Assigned(FChilds) then
|
|
|
|
for i := 0 to FChilds.FCount - 1 do begin
|
|
|
|
Result := FChilds.FItems[i];
|
|
|
|
if Result.Get_NodeNameID = aNameID then
|
|
|
|
Exit
|
|
|
|
end;
|
|
|
|
Result := nil
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetChildText(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aDefault: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlNode;
|
|
|
|
begin
|
|
|
|
aChild := FindFirstChild(aNameID);
|
|
|
|
if Assigned(aChild) then
|
|
|
|
Result := aChild.Get_Text
|
|
|
|
else
|
|
|
|
Result := aDefault
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetChildText(const aName: String;
|
|
|
|
const aDefault: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := GetChildText(FNames.GetID(aName), aDefault);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetEnumAttr(const aName: String;
|
|
|
|
const aValues: array of String; aDefault: Integer): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := GetEnumAttr(FNames.GetID(aName), aValues, aDefault);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function EnumAttrValue(aNode: TXmlNode; anAttrData: PXmlAttrData;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aValues: array of String): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
anAttrValue: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
s: String;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
anAttrValue := anAttrData.Value;
|
|
|
|
for Result := 0 to Length(aValues) - 1 do
|
2013-05-31 16:03:11 +06:00
|
|
|
if CompareText(anAttrValue, aValues[Result]) = 0 then
|
2010-11-06 22:16:58 +02:00
|
|
|
Exit;
|
|
|
|
if Length(aValues) = 0 then
|
|
|
|
s := ''
|
|
|
|
else begin
|
|
|
|
s := aValues[0];
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 1 to Length(aValues) - 1 do begin
|
|
|
|
s := s + ^M+^J + aValues[i];
|
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
raise Exception.CreateFmt(SSimpleXmlError6,
|
|
|
|
[aNode.FNames.GetName(anAttrData.NameID), aNode.Get_NodeName, s]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetEnumAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aValues: array of String; aDefault: Integer): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
anAttrData: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttrData := FindAttrData(aNameID);
|
|
|
|
if Assigned(anAttrData) then
|
|
|
|
Result := EnumAttrValue(Self, anAttrData, aValues)
|
|
|
|
else
|
|
|
|
Result := aDefault;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.NeedEnumAttr(const aName: String;
|
|
|
|
const aValues: array of String): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := NeedEnumAttr(FNames.GetID(aName), aValues)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.NeedEnumAttr(aNameID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aValues: array of String): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
anAttrData: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttrData := FindAttrData(aNameID);
|
|
|
|
if Assigned(anAttrData) then
|
|
|
|
Result := EnumAttrValue(Self, anAttrData, aValues)
|
|
|
|
else
|
|
|
|
raise Exception.CreateFmt(SSimpleXMLError7, [FNames.GetName(aNameID)]);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetFloatAttr(const aName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aDefault: Double): Double;
|
|
|
|
begin
|
|
|
|
Result := GetFloatAttr(FNames.GetID(aName), aDefault);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetFloatAttr(aNameID: Integer;
|
|
|
|
aDefault: Double): Double;
|
|
|
|
var
|
|
|
|
aData: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
aData := FindAttrData(aNameID);
|
|
|
|
if Assigned(aData) then
|
|
|
|
if VarIsNumeric(aData.Value) then
|
|
|
|
Result := aData.Value
|
|
|
|
else
|
|
|
|
Result := XSTRToFloat(aData.Value)
|
|
|
|
else
|
|
|
|
Result := aDefault
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlNode.NeedFloatAttr(aNameID: Integer): Double;
|
|
|
|
var
|
|
|
|
aData: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
aData := FindAttrData(aNameID);
|
|
|
|
if not Assigned(aData) then
|
|
|
|
raise Exception.CreateFmt(SSimpleXmlError8, [FNames.GetName(aNameID)]);
|
|
|
|
|
|
|
|
if VarIsNumeric(aData.Value) then
|
|
|
|
Result := aData.Value
|
|
|
|
else
|
|
|
|
Result := XSTRToFloat(aData.Value)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.NeedFloatAttr(const aName: String): Double;
|
2010-11-06 22:21:34 +02:00
|
|
|
begin
|
|
|
|
Result := NeedFloatAttr(FNames.GetID(aName));
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.NeedIntAttr(const aName: String): Integer;
|
|
|
|
begin
|
|
|
|
Result := NeedIntAttr(FNames.GetID(aName))
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.NeedIntAttr(aNameID: Integer): Integer;
|
|
|
|
var
|
|
|
|
aData: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
aData := FindAttrData(aNameID);
|
|
|
|
if not Assigned(aData) then
|
|
|
|
raise Exception.CreateFmt(SSimpleXmlError8, [FNames.GetName(aNameID)]);
|
|
|
|
|
|
|
|
if VarIsOrdinal(aData.Value) then
|
|
|
|
Result := aData.Value
|
|
|
|
else
|
|
|
|
Result := StrToInt(aData.Value)
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function TXmlNode.GetHexAttr(aNameID, aDefault: Integer): Integer;
|
|
|
|
var
|
|
|
|
anAttr: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttr := FindAttrData(aNameID);
|
|
|
|
if Assigned(anAttr) then
|
|
|
|
Result := StrToInt('$' + anAttr.Value)
|
|
|
|
else
|
|
|
|
Result := aDefault;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetHexAttr(const aName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aDefault: Integer): Integer;
|
|
|
|
begin
|
|
|
|
Result := GetHexAttr(FNames.GetID(aName), aDefault)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetIntAttr(aNameID, aDefault: Integer): Integer;
|
|
|
|
var
|
|
|
|
anAttr: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttr := FindAttrData(aNameID);
|
|
|
|
if Assigned(anAttr) then
|
|
|
|
Result := anAttr.Value
|
|
|
|
else
|
|
|
|
Result := aDefault;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetIntAttr(const aName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aDefault: Integer): Integer;
|
|
|
|
begin
|
|
|
|
Result := GetIntAttr(FNames.GetID(aName), aDefault)
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlNode.NeedVarAttr(aNameID: Integer): Variant;
|
|
|
|
var
|
|
|
|
anAttr: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttr := FindAttrData(aNameID);
|
|
|
|
if not Assigned(anAttr) then
|
|
|
|
raise Exception.CreateFmt(SSimpleXmlError8, [FNames.GetName(aNameID)]);
|
|
|
|
Result := anAttr.Value
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.NeedVarAttr(const aName: String): Variant;
|
2010-11-06 22:21:34 +02:00
|
|
|
begin
|
|
|
|
Result := NeedAttr(FNames.GetID(aName))
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.NeedAttr(aNameID: Integer): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
anAttr: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttr := FindAttrData(aNameID);
|
|
|
|
if not Assigned(anAttr) then
|
|
|
|
raise Exception.CreateFmt(SSimpleXmlError8, [FNames.GetName(aNameID)]);
|
|
|
|
Result := anAttr.Value
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.NeedAttr(const aName: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := NeedAttr(FNames.GetID(aName))
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetVarAttr(aNameID: Integer;
|
|
|
|
const aDefault: Variant): Variant;
|
|
|
|
var
|
|
|
|
anAttr: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttr := FindAttrData(aNameID);
|
|
|
|
if Assigned(anAttr) then
|
|
|
|
Result := anAttr.Value
|
|
|
|
else
|
|
|
|
Result := aDefault;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetVarAttr(const aName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
const aDefault: Variant): Variant;
|
|
|
|
begin
|
|
|
|
Result := GetVarAttr(FNames.GetID(aName), aDefault)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.Get_NodeName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := FNames.GetName(Get_NodeNameID);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetOwnerDocument: TXmlDocument;
|
|
|
|
var
|
|
|
|
aResult: TXmlNode;
|
|
|
|
begin
|
|
|
|
aResult := Self;
|
|
|
|
repeat
|
|
|
|
if aResult is TXmlDocument then
|
|
|
|
break
|
|
|
|
else
|
|
|
|
aResult := aResult.FParentNode;
|
|
|
|
until not Assigned(aResult);
|
|
|
|
Result := TXmlDocument(aResult)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_OwnerDocument: IXmlDocument;
|
|
|
|
var
|
|
|
|
aDoc: TXmlDocument;
|
|
|
|
begin
|
|
|
|
aDoc := GetOwnerDocument;
|
|
|
|
if Assigned(aDoc) then
|
|
|
|
Result := aDoc
|
|
|
|
else
|
|
|
|
Result := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_ParentNode: IXmlNode;
|
|
|
|
begin
|
|
|
|
Result := FParentNode
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlNode.Get_NextSibling: IXmlNode;
|
|
|
|
var
|
|
|
|
anIndex: Integer;
|
|
|
|
begin
|
|
|
|
if Assigned(FParentNode) then begin
|
|
|
|
anIndex := FParentNode.GetChilds.IndexOfNode(Self);
|
|
|
|
if (anIndex >= 0) and (anIndex < FParentNode.FChilds.FCount - 1) then begin
|
|
|
|
Result := FParentNode.FChilds.FItems[anIndex + 1];
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
Result := nil;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function TXmlNode.Get_TypedValue: Variant;
|
|
|
|
begin
|
|
|
|
Result := Get_Text
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.Get_XML: String;
|
2010-11-06 22:21:34 +02:00
|
|
|
var
|
|
|
|
anXml: TStringBuilder;
|
|
|
|
begin
|
|
|
|
anXml.Init;
|
|
|
|
GetXML(anXml);
|
|
|
|
anXml.GetString(Result);
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure TXmlNode.InsertBefore(const aChild, aBefore: IXmlNode);
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
begin
|
|
|
|
aChilds := GetChilds;
|
|
|
|
if Assigned(aBefore) then
|
2010-11-06 22:21:34 +02:00
|
|
|
i := aChilds.IndexOfNode(aBefore.GetObject as TXmlNode)
|
2010-11-06 22:16:58 +02:00
|
|
|
else
|
|
|
|
i := aChilds.FCount;
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild.GetObject as TXmlNode, i)
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.RemoveAllAttrs;
|
|
|
|
begin
|
|
|
|
FAttrCount := 0;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.RemoveAllChilds;
|
|
|
|
begin
|
|
|
|
if Assigned(FChilds) then
|
2010-11-06 22:21:34 +02:00
|
|
|
FChilds.ClearNodes
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.RemoveAttr(const aName: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
RemoveAttr(FNames.GetID(aName));
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.RemoveAttr(aNameID: Integer);
|
|
|
|
var
|
|
|
|
a1, a2: PXmlAttrData;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if FAttrCount = 0 then begin
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
a1 := @FAttrs[0];
|
|
|
|
i := 0;
|
|
|
|
while (i < FAttrCount) and (a1.NameID <> aNameID) do begin
|
|
|
|
Inc(a1);
|
|
|
|
Inc(i)
|
|
|
|
end;
|
|
|
|
if i < FAttrCount then begin
|
|
|
|
a2 := a1;
|
|
|
|
Inc(a2);
|
|
|
|
while i < FAttrCount - 1 do begin
|
|
|
|
a1^ := a2^;
|
|
|
|
Inc(a1);
|
|
|
|
Inc(a2);
|
|
|
|
Inc(i)
|
|
|
|
end;
|
|
|
|
VarClear(a1.Value);
|
|
|
|
Dec(FAttrCount);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.RemoveChild(const aChild: IXmlNode);
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.RemoveNode(aChild.GetObject as TXmlNode)
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.ReplaceChild(const aNewChild, anOldChild: IXmlNode);
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
begin
|
|
|
|
aChilds := GetChilds;
|
2010-11-06 22:21:34 +02:00
|
|
|
i := aChilds.IndexOfNode(anOldChild.GetObject as TXmlNode);
|
2010-11-06 22:16:58 +02:00
|
|
|
if i <> -1 then
|
2010-11-06 22:21:34 +02:00
|
|
|
aChilds.ReplaceNode(i, aNewChild.GetObject as TXmlNode)
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function NameCanBeginWith(aChar: Char): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := (aChar = '_') or IsCharAlpha(aChar)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function NameCanContain(aChar: Char): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := (aChar = '_') or (aChar = '-') or (aChar = ':') or (aChar = '.') or
|
2013-05-31 16:03:11 +06:00
|
|
|
IsCharAlphaNumeric(aChar)
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function IsName(const s: String): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
if s = '' then
|
|
|
|
Result := False
|
|
|
|
else if not NameCanBeginWith(s[1]) then
|
|
|
|
Result := False
|
|
|
|
else begin
|
|
|
|
for i := 2 to Length(s) do
|
|
|
|
if not NameCanContain(s[i]) then begin
|
|
|
|
Result := False;
|
|
|
|
Exit
|
|
|
|
end;
|
|
|
|
Result := True;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
const
|
|
|
|
ntComment = -2;
|
|
|
|
ntNode = -3;
|
|
|
|
ntProcessingInstruction = -4;
|
|
|
|
ntText = -5;
|
|
|
|
|
|
|
|
type
|
|
|
|
TAxis = (axAncestor, axAncestorOrSelf, axAttribute, axChild,
|
|
|
|
axDescendant, axDescendantOrSelf, axFollowing, axFollowingSibling,
|
|
|
|
axParent, axPreceding, axPrecedingSibling, axSelf);
|
|
|
|
|
|
|
|
TPredicate = class
|
|
|
|
function Check(aNode: TXmlNode): Boolean; virtual; abstract;
|
|
|
|
end;
|
|
|
|
|
|
|
|
TLocationStep = class
|
|
|
|
Next: TLocationStep;
|
|
|
|
Axis: TAxis;
|
|
|
|
NodeTest: Integer;
|
|
|
|
Predicates: TList;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function TXmlNode.SelectNodes(
|
2013-05-31 16:03:11 +06:00
|
|
|
const anExpression: String): IXmlNodeList;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aNodes: TXmlNodeList;
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
aChild: TXmlNode;
|
|
|
|
aNameID: Integer;
|
|
|
|
i: Integer;
|
|
|
|
{
|
|
|
|
aPath: TXmlPath;
|
|
|
|
}
|
|
|
|
begin
|
|
|
|
if IsName(anExpression) then begin
|
|
|
|
aNodes := TXmlNodeList.Create(nil);
|
|
|
|
Result := aNodes;
|
|
|
|
aChilds := GetChilds;
|
|
|
|
aNameID := FNames.GetID(anExpression);
|
|
|
|
for i := 0 to aChilds.FCount - 1 do begin
|
|
|
|
aChild := aChilds.FItems[i];
|
|
|
|
if (aChild.Get_NodeType = NODE_ELEMENT) and (aChild.Get_NodeNameID = aNameID) then
|
2010-11-06 22:21:34 +02:00
|
|
|
aNodes.InsertNode(aChild, aNodes.FCount);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
raise
|
|
|
|
Exception.Create(SSimpleXmlError9);
|
|
|
|
{
|
|
|
|
aPath := TXmlPath.Create;
|
|
|
|
try
|
|
|
|
aPath.Init(anExpression);
|
|
|
|
Result := aPath.SelectNodes(Self);
|
|
|
|
finally
|
|
|
|
aPath.Free
|
|
|
|
end
|
|
|
|
}
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlNode.SelectNodes(aNodeNameID: Integer): IXmlNodeList;
|
|
|
|
var
|
|
|
|
aNodes: TXmlNodeList;
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
aChild: TXmlNode;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
aNodes := TXmlNodeList.Create(nil);
|
|
|
|
Result := aNodes;
|
|
|
|
aChilds := GetChilds;
|
|
|
|
for i := 0 to aChilds.FCount - 1 do begin
|
|
|
|
aChild := aChilds.FItems[i];
|
|
|
|
if aChild.Get_NodeNameID = aNodeNameID then
|
|
|
|
aNodes.InsertNode(aChild, aNodes.FCount);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.SelectSingleNode(const anExpression: String): IXmlNode;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
aChild: TXmlNode;
|
|
|
|
aNameID: Integer;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
if IsName(anExpression) then begin
|
|
|
|
aChilds := GetChilds;
|
|
|
|
aNameID := FNames.GetID(anExpression);
|
|
|
|
for i := 0 to aChilds.FCount - 1 do begin
|
|
|
|
aChild := aChilds.FItems[i];
|
|
|
|
if (aChild.Get_NodeType = NODE_ELEMENT) and (aChild.Get_NodeNameID = aNameID) then begin
|
|
|
|
Result := aChild;
|
|
|
|
Exit
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
Result := nil;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
raise
|
|
|
|
Exception.Create(SSimpleXmlError9)
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.FindElement(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlElement;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlNode;
|
|
|
|
aNameID, anAttrNameID: Integer;
|
|
|
|
i: Integer;
|
|
|
|
pa: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
if Assigned(FChilds) then begin
|
|
|
|
aNameID := FNames.GetID(anElementName);
|
|
|
|
anAttrNameID := FNames.GetID(anAttrName);
|
|
|
|
|
|
|
|
for i := 0 to FChilds.FCount - 1 do begin
|
|
|
|
aChild := FChilds.FItems[i];
|
|
|
|
if (aChild.Get_NodeType = NODE_ELEMENT) and (aChild.Get_NodeNameID = aNameID) then begin
|
|
|
|
pa := aChild.FindAttrData(anAttrNameID);
|
|
|
|
try
|
|
|
|
if Assigned(pa) and VarSameValue(pa.Value, anAttrValue) then begin
|
|
|
|
Result := aChild.AsElement;
|
|
|
|
Exit
|
|
|
|
end
|
|
|
|
except
|
|
|
|
// �������������� �������� ����� ���������� � ��� ������,
|
|
|
|
// ���� ���������� ���� � ������� VarSameValue.
|
|
|
|
// ����� ������� - ���� �������� ������ ����������.
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
Result := nil;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlNode.FindElements(const anElementName, anAttrName: String; const anAttrValue: Variant): IXmlNodeList;
|
|
|
|
var
|
|
|
|
aNodes: TXmlNodeList;
|
|
|
|
aChild: TXmlNode;
|
|
|
|
aNameID, anAttrNameID: Integer;
|
|
|
|
i: Integer;
|
|
|
|
pa: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
aNodes := TXmlNodeList.Create(nil);
|
|
|
|
Result := aNodes;
|
|
|
|
if Assigned(FChilds) then begin
|
|
|
|
aNameID := FNames.GetID(anElementName);
|
|
|
|
anAttrNameID := FNames.GetID(anAttrName);
|
|
|
|
|
|
|
|
for i := 0 to FChilds.FCount - 1 do begin
|
|
|
|
aChild := FChilds.FItems[i];
|
|
|
|
if (aChild.Get_NodeType = NODE_ELEMENT) and (aChild.Get_NodeNameID = aNameID) then begin
|
|
|
|
pa := aChild.FindAttrData(anAttrNameID);
|
|
|
|
try
|
|
|
|
if Assigned(pa) and VarSameValue(pa.Value, anAttrValue) then
|
|
|
|
aNodes.InsertNode(aChild, aNodes.FCount);
|
|
|
|
except
|
|
|
|
// �������������� �������� ����� ���������� � ��� ������,
|
|
|
|
// ���� ���������� ���� � ������� VarSameValue.
|
|
|
|
// ����� ������� - ���� �������� ������ ����������.
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure TXmlNode.Set_TypedValue(const aValue: Variant);
|
|
|
|
begin
|
|
|
|
Set_Text(aValue)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetAttr(const aName, aValue: String);
|
2011-10-25 17:40:37 +04:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
SetVarAttr(FNames.GetID(aName), aValue)
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetAttr(aNameID: Integer; const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
SetVarAttr(aNameID, aValue)
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetBoolAttr(aNameID: Integer; aValue: Boolean);
|
|
|
|
begin
|
|
|
|
SetVarAttr(aNameID, aValue)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetBoolAttr(const aName: String; aValue: Boolean);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
SetVarAttr(FNames.GetID(aName), aValue)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetChildText(const aName: String;
|
|
|
|
const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
SetChildText(FNames.GetID(aName), aValue)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetChildText(aNameID: Integer; const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlNode;
|
|
|
|
begin
|
|
|
|
aChild := FindFirstChild(aNameID);
|
|
|
|
if not Assigned(aChild) then begin
|
|
|
|
aChild := TXmlElement.Create(FNames, aNameID);
|
|
|
|
with GetChilds do
|
2010-11-06 22:21:34 +02:00
|
|
|
InsertNode(aChild, FCount);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
aChild.Set_Text(aValue)
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetFloatAttr(aNameID: Integer; aValue: Double);
|
|
|
|
begin
|
|
|
|
SetVarAttr(aNameID, aValue)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetFloatAttr(const aName: String; aValue: Double);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
SetVarAttr(FNames.GetID(aName), aValue);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetHexAttr(const aName: String; aValue,
|
2010-11-06 22:16:58 +02:00
|
|
|
aDigits: Integer);
|
|
|
|
begin
|
|
|
|
SetVarAttr(FNames.GetID(aName), IntToHex(aValue, aDigits))
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetHexAttr(aNameID, aValue, aDigits: Integer);
|
|
|
|
begin
|
|
|
|
SetVarAttr(aNameID, IntToHex(aValue, aDigits))
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetIntAttr(aNameID, aValue: Integer);
|
|
|
|
begin
|
|
|
|
SetVarAttr(aNameID, aValue)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetIntAttr(const aName: String; aValue: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
SetVarAttr(FNames.GetID(aName), aValue)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetVarAttr(const aName: String; aValue: Variant);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
SetVarAttr(FNames.GetID(aName), aValue)
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetVarAttr(aNameID: Integer; const aValue: Variant);
|
|
|
|
var
|
|
|
|
anAttr: PXmlAttrData;
|
|
|
|
var
|
|
|
|
aDelta: Integer;
|
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
if aNameID = -1 then
|
|
|
|
raise Exception.Create(SSimpleXmlError27);
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
anAttr := FindAttrData(aNameID);
|
|
|
|
if not Assigned(anAttr) then begin
|
|
|
|
if FAttrCount = Length(FAttrs) then begin
|
|
|
|
if FAttrCount > 64 then
|
|
|
|
aDelta := FAttrCount div 4
|
|
|
|
else if FAttrCount > 8 then
|
|
|
|
aDelta := 16
|
|
|
|
else
|
|
|
|
aDelta := 4;
|
|
|
|
SetLength(FAttrs, FAttrCount + aDelta);
|
|
|
|
end;
|
|
|
|
anAttr := @FAttrs[FAttrCount];
|
|
|
|
anAttr.NameID := aNameID;
|
|
|
|
Inc(FAttrCount);
|
|
|
|
end;
|
|
|
|
anAttr.Value := aValue
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.FindAttrData(aNameID: Integer): PXmlAttrData;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if FAttrCount = 0 then begin
|
|
|
|
Result := nil;
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := @FAttrs[0];
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to FAttrCount - 1 do begin
|
|
|
|
if Result.NameID = aNameID then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Exit
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(Result);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AsElement: IXmlElement;
|
|
|
|
begin
|
|
|
|
Result := nil
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AsCDATASection: IXmlCDATASection;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
Result := nil
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AsComment: IXmlComment;
|
|
|
|
begin
|
|
|
|
Result := nil
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AsText: IXmlText;
|
|
|
|
begin
|
|
|
|
Result := nil
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AsProcessingInstruction: IXmlProcessingInstruction;
|
|
|
|
begin
|
|
|
|
Result := nil
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.AppendCDATA(const aData: String): IXmlCDATASection;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlCDATASection;
|
|
|
|
begin
|
|
|
|
aChild := TXmlCDATASection.Create(FNames, aData);
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.AppendComment(const aData: String): IXmlComment;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlComment;
|
|
|
|
begin
|
|
|
|
aChild := TXmlComment.Create(FNames, aData);
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.AppendElement(const aName: String): IXmlElement;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlElement;
|
|
|
|
begin
|
|
|
|
aChild := TXmlElement.Create(FNames, FNames.GetID(aName));
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AppendElement(aNameID: Integer): IXmlElement;
|
|
|
|
var
|
|
|
|
aChild: TXmlElement;
|
|
|
|
begin
|
|
|
|
aChild := TXmlElement.Create(FNames, aNameID);
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AppendProcessingInstruction(const aTarget,
|
2013-05-31 16:03:11 +06:00
|
|
|
aData: String): IXmlProcessingInstruction;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlProcessingInstruction;
|
|
|
|
begin
|
|
|
|
aChild := TXmlProcessingInstruction.Create(FNames, FNames.GetID(aTarget), aData);
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AppendProcessingInstruction(aTargetID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String): IXmlProcessingInstruction;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlProcessingInstruction;
|
|
|
|
begin
|
|
|
|
aChild := TXmlProcessingInstruction.Create(FNames, aTargetID, aData);
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.AppendText(const aData: String): IXmlText;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChild: TXmlText;
|
|
|
|
begin
|
|
|
|
aChild := TXmlText.Create(FNames, aData);
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.InsertNode(aChild, -1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlNode.GetAttrsXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
a: PXmlAttrData;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
if FAttrCount > 0 then begin
|
|
|
|
a := @FAttrs[0];
|
|
|
|
for i := 0 to FAttrCount - 1 do begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add(' ' + FNames.GetName(a.NameID) + '="' + TextToXML(VarToXSTR(TVarData(a.Value))) + '"');
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(a);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.LoadBinXml(aReader: TBinaryXmlReader);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aCount: LongInt;
|
|
|
|
a: PXmlAttrData;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
// ������� ��������
|
|
|
|
RemoveAllAttrs;
|
|
|
|
aCount := aReader.ReadLongint;
|
|
|
|
SetLength(FAttrs, aCount);
|
|
|
|
FAttrCount := aCount;
|
2013-05-31 16:03:11 +06:00
|
|
|
if aCount > 0 then begin
|
|
|
|
a := @FAttrs[0];
|
|
|
|
for i := 0 to aCount - 1 do begin
|
|
|
|
a.NameID := aReader.ReadLongint;
|
|
|
|
aReader.ReadVariant(TVarData(a.Value));
|
|
|
|
Inc(a);
|
|
|
|
end;
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// ������� �������� ����
|
|
|
|
aCount := aReader.ReadLongint;
|
|
|
|
if aCount > 0 then
|
|
|
|
GetChilds.LoadBinXml(aReader, aCount, FNames);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SaveBinXml(aWriter: TBinaryXmlWriter);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aCount: LongInt;
|
|
|
|
a: PXmlAttrData;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
// ������� ��������
|
|
|
|
aCount := FAttrCount;
|
|
|
|
aWriter.WriteLongint(aCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
if aCount > 0 then begin
|
|
|
|
a := @FAttrs[0];
|
|
|
|
for i := 0 to aCount - 1 do begin
|
|
|
|
aWriter.WriteLongint(a.NameID);
|
|
|
|
aWriter.WriteVariant(TVarData(a.Value));
|
|
|
|
Inc(a);
|
|
|
|
end;
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
// �������� �������� ����
|
|
|
|
if Assigned(FChilds) then begin
|
|
|
|
aWriter.WriteLongint(FChilds.FCount);
|
|
|
|
FChilds.SaveBinXml(aWriter);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
aWriter.WriteLongint(0);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_DataType: Integer;
|
|
|
|
begin
|
|
|
|
Result := varString
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.AttrExists(aNameID: Integer): Boolean;
|
|
|
|
begin
|
|
|
|
Result := FindAttrData(aNameID) <> nil
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.AttrExists(const aName: String): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := FindAttrData(FNames.GetID(aName)) <> nil
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetAttrType(aNameID: Integer): Integer;
|
|
|
|
var
|
|
|
|
a: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
a := FindAttrData(aNameID);
|
2013-05-31 16:03:11 +06:00
|
|
|
if Assigned(a) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := TVarData(a.Value).VType
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := varString
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetAttrType(const aName: String): Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := GetAttrType(FNames.GetID(aName));
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_Values(const aName: String): Variant;
|
|
|
|
var
|
|
|
|
aChild: IXmlNode;
|
|
|
|
begin
|
|
|
|
if aName = '' then
|
|
|
|
Result := Get_TypedValue
|
|
|
|
else if aName[1] = '@' then
|
|
|
|
Result := GetVarAttr(Copy(aName, 2, Length(aName) - 1), '')
|
|
|
|
else begin
|
|
|
|
aChild := SelectSingleNode(aName);
|
|
|
|
if Assigned(aChild) then
|
|
|
|
Result := aChild.TypedValue
|
|
|
|
else
|
|
|
|
Result := ''
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.Set_Values(const aName: String; const aValue: Variant);
|
|
|
|
var
|
|
|
|
aChild: IXmlNode;
|
|
|
|
begin
|
|
|
|
if aName = '' then
|
|
|
|
Set_TypedValue(aValue)
|
|
|
|
else if aName[1] = '@' then
|
|
|
|
SetVarAttr(Copy(aName, 2, Length(aName) - 1), aValue)
|
|
|
|
else begin
|
|
|
|
aChild := SelectSingleNode(aName);
|
|
|
|
if not Assigned(aChild) then
|
|
|
|
aChild := AppendElement(aName);
|
|
|
|
aChild.TypedValue := aValue;
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.GetDateTimeAttr(aNameID: Integer;
|
|
|
|
aDefault: TDateTime): TDateTime;
|
|
|
|
var
|
|
|
|
anAttr: PXmlAttrData;
|
|
|
|
begin
|
|
|
|
anAttr := FindAttrData(aNameID);
|
|
|
|
if Assigned(anAttr) then begin
|
|
|
|
if (VarType(anAttr.Value) = varString) or (VarType(anAttr.Value) = varOleStr) then
|
|
|
|
Result := XSTRToDateTime(anAttr.Value)
|
|
|
|
else
|
|
|
|
Result := VarAsType(anAttr.Value, varDate)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
Result := aDefault;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetDateTimeAttr(const aName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aDefault: TDateTime): TDateTime;
|
|
|
|
begin
|
|
|
|
Result := GetDateTimeAttr(FNames.GetID(aName), aDefault)
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetDateTimeAttr(aNameID: Integer; aValue: TDateTime);
|
|
|
|
begin
|
|
|
|
SetVarAttr(aNameID, VarAsType(aValue, varDate))
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.SetDateTimeAttr(const aName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aValue: TDateTime);
|
|
|
|
begin
|
|
|
|
SetVarAttr(aName, VarAsType(aValue, varDate))
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.EnsureChild(aNameID: Integer): IXmlNode;
|
|
|
|
var
|
|
|
|
aChild: TXmlNode;
|
|
|
|
begin
|
|
|
|
aChild := FindFirstChild(aNameID);
|
|
|
|
if Assigned(aChild) then
|
|
|
|
Result := aChild
|
|
|
|
else
|
|
|
|
Result := AppendElement(aNameID)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.EnsureChild(const aName: String): IXmlNode;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := EnsureChild(FNames.GetID(aName))
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.NeedChild(aNameID: Integer): IXmlNode;
|
|
|
|
var
|
|
|
|
aChild: TXmlNode;
|
|
|
|
begin
|
|
|
|
aChild := FindFirstChild(aNameID);
|
|
|
|
if not Assigned(aChild) then
|
|
|
|
raise Exception.CreateFmt(SSimpleXmlError10, [FNames.GetName(aNameID)]);
|
|
|
|
Result := aChild
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.NeedChild(const aName: String): IXmlNode;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := NeedChild(FNames.GetID(aName));
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetNameTable(aValue: TXmlNameTable; aMap: TList);
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aNewMap: Boolean;
|
|
|
|
begin
|
|
|
|
if aValue <> FNames then begin
|
|
|
|
aNewMap := not Assigned(aMap);
|
|
|
|
if aNewMap then begin
|
|
|
|
aMap := TList.Create;
|
2010-11-06 22:21:34 +02:00
|
|
|
for i := 0 to Length(FNames.FNames) - 1 do
|
2010-11-06 22:16:58 +02:00
|
|
|
aMap.Add(Pointer(aValue.GetID(FNames.FNames[i])));
|
|
|
|
end;
|
|
|
|
try
|
|
|
|
SetNodeNameID(Integer(aMap[Get_NodeNameID]));
|
2010-11-06 22:21:34 +02:00
|
|
|
for i := 0 to Length(FAttrs) - 1 do
|
2010-11-06 22:16:58 +02:00
|
|
|
with FAttrs[i] do
|
|
|
|
NameID := Integer(aMap[NameID]);
|
2010-11-06 22:21:34 +02:00
|
|
|
FNames._Release;
|
|
|
|
FNames := aValue;
|
|
|
|
aValue._AddRef;
|
2010-11-06 22:16:58 +02:00
|
|
|
if Assigned(FChilds) then
|
|
|
|
for i := 0 to FChilds.FCount - 1 do
|
|
|
|
FChilds.FItems[i].SetNameTable(aValue, aMap);
|
|
|
|
finally
|
|
|
|
if aNewMap then
|
|
|
|
aMap.Free
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.SetNodeNameID(aValue: Integer);
|
|
|
|
begin
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function TXmlNode.CloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
begin
|
|
|
|
Result := DoCloneNode(aDeep)
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
|
|
|
|
function TXmlNode.Get_SourceLine: Integer;
|
|
|
|
begin
|
|
|
|
Result := FSourceLine
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlNode.Get_SourceCol: Integer;
|
|
|
|
begin
|
|
|
|
Result := FSourceCol
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetTextAsBinaryData: RawByteString;
|
2010-11-06 22:21:34 +02:00
|
|
|
begin
|
|
|
|
Result := Base64ToBin(Get_Text);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlNode.GetOwnText: String;
|
2010-11-06 22:21:34 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
sb: TStringBuilder;
|
|
|
|
begin
|
|
|
|
sb.Init;
|
|
|
|
for i := 0 to GetChilds.FCount - 1 do
|
|
|
|
with FChilds.FItems[i] do
|
|
|
|
if Get_NodeType in [NODE_TEXT, NODE_CDATA_SECTION] then
|
|
|
|
sb.Add(Get_Text);
|
|
|
|
sb.GetString(Result);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.ReplaceTextByBinaryData(const aData; aSize: Integer;
|
2010-11-06 22:21:34 +02:00
|
|
|
aMaxLineLength: Integer);
|
|
|
|
begin
|
|
|
|
RemoveTextNodes;
|
|
|
|
GetChilds.InsertNode(TXmlText.Create(FNames, BinToBase64(aData, aSize, aMaxLineLength)), -1);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlNode.RemoveTextNodes;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aNode: TXmlNode;
|
|
|
|
begin
|
|
|
|
if Assigned(FChilds) then
|
|
|
|
for i := FChilds.FCount - 1 downto 0 do begin
|
|
|
|
aNode := FChilds.FItems[i];
|
|
|
|
if aNode.Get_NodeType in [NODE_TEXT, NODE_CDATA_SECTION] then
|
|
|
|
FChilds.RemoveNode(aNode);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlNode.ReplaceTextByCDATASection(const aText: String);
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure AddCDATASection(const aText: String);
|
2010-11-06 22:21:34 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
begin
|
|
|
|
i := Pos(']]>', aText);
|
|
|
|
aChilds := GetChilds;
|
|
|
|
if i = 0 then
|
|
|
|
aChilds.InsertNode(TXmlCDATASection.Create(FNames, aText), aChilds.FCount)
|
|
|
|
else begin
|
|
|
|
aChilds.InsertNode(TXmlCDATASection.Create(FNames, Copy(aText, 1, i)), aChilds.FCount);
|
|
|
|
AddCDATASection(Copy(aText, i + 1, Length(aText) - i - 1));
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
begin
|
|
|
|
RemoveTextNodes;
|
|
|
|
AddCDATASection(aText);
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
{ TXmlElement }
|
|
|
|
|
|
|
|
constructor TXmlElement.Create(aNames: TXmlNameTable; aNameID: Integer);
|
|
|
|
begin
|
|
|
|
inherited Create(aNames);
|
|
|
|
FNameID := aNameID;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.Get_NodeNameID: Integer;
|
|
|
|
begin
|
|
|
|
Result := FNameID
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.Get_NodeType: Integer;
|
|
|
|
begin
|
|
|
|
Result := NODE_ELEMENT
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.GetChilds: TXmlNodeList;
|
2010-11-06 22:21:34 +02:00
|
|
|
var
|
|
|
|
aText: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := inherited GetChilds;
|
2010-11-06 22:21:34 +02:00
|
|
|
if not (VarIsEmpty(FData) or VarIsNull(FData)) then begin
|
|
|
|
aText := VarToXSTR(TVarData(FData));
|
2010-11-06 22:16:58 +02:00
|
|
|
VarClear(FData);
|
2010-11-06 22:21:34 +02:00
|
|
|
if aText <> '' then
|
|
|
|
AppendText(aText);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlElement.Get_Text: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
aChild: TXmlNode;
|
2013-05-31 16:03:11 +06:00
|
|
|
aChildText: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
Result := '';
|
|
|
|
if Assigned(FChilds) and (FChilds.FCount > 0) then begin
|
|
|
|
aChilds := FChilds;
|
|
|
|
for i := 0 to aChilds.FCount - 1 do begin
|
|
|
|
aChild := aChilds.FItems[i];
|
|
|
|
if aChild.Get_NodeType in [NODE_ELEMENT, NODE_TEXT, NODE_CDATA_SECTION] then begin
|
|
|
|
aChildText := aChild.Get_Text;
|
|
|
|
if aChildText <> '' then
|
|
|
|
if Result = '' then
|
|
|
|
Result := aChildText
|
|
|
|
else
|
|
|
|
Result := Result + ' ' + aChildText
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else if VarIsEmpty(FData) then
|
|
|
|
Result := ''
|
|
|
|
else
|
|
|
|
Result := VarToXSTR(TVarData(FData))
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlElement.Set_Text(const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
if Assigned(FChilds) then
|
2010-11-06 22:21:34 +02:00
|
|
|
FChilds.ClearNodes;
|
2010-11-06 22:16:58 +02:00
|
|
|
FData := aValue;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.AsElement: IXmlElement;
|
|
|
|
begin
|
|
|
|
Result := Self
|
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
FGetXMLIntend: Integer = 0;
|
|
|
|
|
|
|
|
function GetIndentStr: String;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
SetLength(Result, FGetXMLIntend*Length(DefaultIndentText));
|
|
|
|
for i := 0 to FGetXMLIntend - 1 do
|
|
|
|
Move(DefaultIndentText[1], Result[i*Length(DefaultIndentText) + 1], Length(DefaultIndentText));
|
|
|
|
end;
|
|
|
|
|
|
|
|
function HasCRLF(const s: String): Boolean;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
for i := 1 to Length(s) do
|
|
|
|
if (s[i] = ^M) or (s[i] = ^J) then begin
|
|
|
|
Result := True;
|
|
|
|
Exit
|
|
|
|
end;
|
|
|
|
Result := False;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function EndWithCRLF(const s: String): Boolean;
|
|
|
|
begin
|
|
|
|
Result :=
|
|
|
|
(Length(s) > 1) and
|
|
|
|
(s[Length(s) - 1] = ^M) and
|
|
|
|
(s[Length(s)] = ^J);
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlElement.GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2010-11-06 22:21:34 +02:00
|
|
|
aChildsXMLSB: TStringBuilder;
|
|
|
|
aChildsXML: String;
|
2013-05-31 16:03:11 +06:00
|
|
|
aTag: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aDoc: TXmlDocument;
|
|
|
|
aPreserveWhiteSpace: Boolean;
|
2010-11-06 22:21:34 +02:00
|
|
|
aSaveLength: Integer;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
aDoc := GetOwnerDocument;
|
|
|
|
if Assigned(aDoc) then
|
|
|
|
aPreserveWhiteSpace := aDoc.Get_PreserveWhiteSpace
|
|
|
|
else
|
|
|
|
aPreserveWhiteSpace := DefaultPreserveWhiteSpace;
|
|
|
|
if aPreserveWhiteSpace then begin
|
|
|
|
aTag := FNames.GetName(FNameID);
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add('<');
|
|
|
|
anXml.Add(aTag);
|
|
|
|
GetAttrsXML(anXml);
|
|
|
|
anXml.Add(' ');
|
|
|
|
aSaveLength := anXml.FLength;
|
|
|
|
if Assigned(FChilds) and (FChilds.FCount > 0) then
|
|
|
|
FChilds.GetXML(anXml)
|
|
|
|
else if not VarIsEmpty(FData) then
|
|
|
|
anXml.Add(TextToXML(VarToXSTR(TVarData(FData))));
|
|
|
|
|
|
|
|
if anXml.FLength = aSaveLength then begin
|
|
|
|
anXml.FData[aSaveLength] := '/';
|
|
|
|
anXml.Add('>')
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
anXml.FData[aSaveLength] := '>';
|
|
|
|
anXml.Add('</');
|
|
|
|
anXml.Add(aTag);
|
|
|
|
anXml.Add('>')
|
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if Assigned(FChilds) and (FChilds.FCount > 0) then begin
|
|
|
|
Inc(FGetXMLIntend);
|
|
|
|
try
|
2010-11-06 22:21:34 +02:00
|
|
|
aChildsXMLSB.Init;
|
|
|
|
FChilds.GetXML(aChildsXMLSB);
|
|
|
|
aChildsXMLSB.GetString(aChildsXML);
|
2010-11-06 22:16:58 +02:00
|
|
|
finally
|
|
|
|
Dec(FGetXMLIntend)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else if VarIsEmpty(FData) then
|
2010-11-06 22:21:34 +02:00
|
|
|
aChildsXML := ''
|
|
|
|
else
|
2010-11-06 22:16:58 +02:00
|
|
|
aChildsXML := TextToXML(VarToXSTR(TVarData(FData)));
|
|
|
|
aTag := FNames.GetName(FNameID);
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add(^M^J); anXml.Add(GetIndentStr); anXml.Add('<'); anXml.Add(aTag);
|
|
|
|
GetAttrsXML(anXml);
|
2010-11-06 22:16:58 +02:00
|
|
|
if aChildsXML = '' then
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add('/>')
|
2010-11-06 22:16:58 +02:00
|
|
|
else if HasCRLF(aChildsXML) then
|
2010-11-06 22:21:34 +02:00
|
|
|
if EndWithCRLF(aChildsXML) then begin
|
|
|
|
anXml.Add('>'); anXml.Add(aChildsXML); anXml.Add(GetIndentStr);
|
|
|
|
anXml.Add('</'); anXml.Add(aTag); anXml.Add('>')
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
anXml.Add('>'); anXml.Add(aChildsXML); anXml.Add(^M^J); anXml.Add(GetIndentStr);
|
|
|
|
anXml.Add('</'); anXml.Add(aTag); anXml.Add('>')
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
anXml.Add('>');
|
|
|
|
anXml.Add(aChildsXML);
|
|
|
|
anXml.Add('</');
|
|
|
|
anXml.Add(aTag);
|
|
|
|
anXml.Add('>');
|
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.Get_TypedValue: Variant;
|
|
|
|
begin
|
|
|
|
if Assigned(FChilds) and (FChilds.FCount > 0) then
|
|
|
|
Result := Get_Text
|
|
|
|
else
|
|
|
|
Result := FData
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlElement.Set_TypedValue(const aValue: Variant);
|
|
|
|
begin
|
|
|
|
if Assigned(FChilds) then
|
2010-11-06 22:21:34 +02:00
|
|
|
FChilds.ClearNodes;
|
2010-11-06 22:16:58 +02:00
|
|
|
FData := aValue;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.Get_DataType: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if (Assigned(FChilds) and (FChilds.FCount > 0)) or VarIsEmpty(FData) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := varString
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := TVarData(FData).VType;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.Get_ChildNodes: IXmlNodeList;
|
|
|
|
begin
|
|
|
|
Result := inherited Get_ChildNodes;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlElement.SetNodeNameID(aValue: Integer);
|
|
|
|
begin
|
|
|
|
FNameID := aValue
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlElement.DoCloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
var
|
|
|
|
aClone: TXmlElement;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
aClone := TXmlElement.Create(FNames, FNameID);
|
|
|
|
Result := aClone;
|
|
|
|
SetLength(aClone.FAttrs, FAttrCount);
|
|
|
|
aClone.FAttrCount := FAttrCount;
|
|
|
|
for i := 0 to FAttrCount - 1 do
|
|
|
|
aClone.FAttrs[i] := FAttrs[i];
|
2010-11-06 22:21:34 +02:00
|
|
|
aClone.FData := FData;
|
2010-11-06 22:16:58 +02:00
|
|
|
if aDeep and Assigned(FChilds) and (FChilds.FCount > 0) then
|
|
|
|
for i := 0 to FChilds.FCount - 1 do
|
|
|
|
aClone.AppendChild(FChilds.FItems[i].CloneNode(True));
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlCharacterData }
|
|
|
|
|
|
|
|
constructor TXmlCharacterData.Create(aNames: TXmlNameTable;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
inherited Create(aNames);
|
|
|
|
FData := aData;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlCharacterData.Get_Text: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aDoc: TXmlDocument;
|
|
|
|
aPreserveWhiteSpace: Boolean;
|
|
|
|
begin
|
|
|
|
aDoc := GetOwnerDocument;
|
|
|
|
if Assigned(aDoc) then
|
|
|
|
aPreserveWhiteSpace := aDoc.Get_PreserveWhiteSpace
|
|
|
|
else
|
|
|
|
aPreserveWhiteSpace := DefaultPreserveWhiteSpace;
|
|
|
|
if aPreserveWhiteSpace then
|
|
|
|
Result := FData
|
|
|
|
else
|
|
|
|
Result := Trim(FData);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlCharacterData.Set_Text(const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FData := aValue
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlText }
|
|
|
|
|
|
|
|
function TXmlText.AsText: IXmlText;
|
|
|
|
begin
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TXmlText.Create(aNames: TXmlNameTable; const aData: Variant);
|
|
|
|
begin
|
|
|
|
inherited Create(aNames);
|
|
|
|
FData := aData;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlText.DoCloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
begin
|
|
|
|
Result := TXmlText.Create(FNames, FData);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlText.Get_DataType: Integer;
|
|
|
|
begin
|
|
|
|
Result := TVarData(FData).VType
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlText.Get_NodeNameID: Integer;
|
|
|
|
begin
|
|
|
|
Result := FNames.FXmlTextNameID
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlText.Get_NodeType: Integer;
|
|
|
|
begin
|
|
|
|
Result := NODE_TEXT
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlText.Get_Text: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := VarToXSTR(TVarData(FData))
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlText.Get_TypedValue: Variant;
|
|
|
|
begin
|
|
|
|
Result := FData
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlText.GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add(TextToXML(VarToXSTR(TVarData(FData))));
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlText.Set_Text(const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FData := aValue
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlText.Set_TypedValue(const aValue: Variant);
|
|
|
|
begin
|
|
|
|
FData := aValue
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlCDATASection }
|
|
|
|
|
|
|
|
function TXmlCDATASection.AsCDATASection: IXmlCDATASection;
|
|
|
|
begin
|
|
|
|
Result := Self
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlCDATASection.DoCloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
begin
|
|
|
|
Result := TXmlCDATASection.Create(FNames, FData);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlCDATASection.Get_NodeNameID: Integer;
|
|
|
|
begin
|
|
|
|
Result := FNames.FXmlCDATASectionNameID
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlCDATASection.Get_NodeType: Integer;
|
|
|
|
begin
|
|
|
|
Result := NODE_CDATA_SECTION
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function GenCDATAXML(const aValue: String): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
i := Pos(']]>', aValue);
|
|
|
|
if i = 0 then
|
|
|
|
Result := '<![CDATA[' + aValue + ']]>'
|
|
|
|
else
|
|
|
|
Result := '<![CDATA[' + Copy(aValue, 1, i) + ']]>' + GenCDATAXML(Copy(aValue, i + 1, Length(aValue) - i - 1));
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlCDATASection.GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add(GenCDATAXML(FData));
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlComment }
|
|
|
|
|
|
|
|
function TXmlComment.AsComment: IXmlComment;
|
|
|
|
begin
|
|
|
|
Result := Self
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlComment.DoCloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
begin
|
|
|
|
Result := TXmlComment.Create(FNames, FData);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlComment.Get_NodeNameID: Integer;
|
|
|
|
begin
|
|
|
|
Result := FNames.FXmlCommentNameID
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlComment.Get_NodeType: Integer;
|
|
|
|
begin
|
|
|
|
Result := NODE_COMMENT
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlComment.GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add('<!--');
|
|
|
|
anXml.Add(FData);
|
|
|
|
anXml.Add('-->');
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlDocument }
|
|
|
|
|
|
|
|
constructor TXmlDocument.Create(aNames: TXmlNameTable);
|
|
|
|
begin
|
|
|
|
inherited Create(aNames);
|
|
|
|
FPreserveWhiteSpace := DefaultPreserveWhiteSpace;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.CreateCDATASection(
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String): IXmlCDATASection;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlCDATASection.Create(FNames, aData)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlDocument.CreateComment(const aData: String): IXmlComment;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlComment.Create(FNames, aData)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.CreateElement(aNameID: Integer): IXmlElement;
|
|
|
|
begin
|
|
|
|
Result := TXmlElement.Create(FNames, aNameID)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlDocument.CreateElement(const aName: String): IXmlElement;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlElement.Create(FNames, FNames.GetID(aName));
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.CreateProcessingInstruction(const aTarget,
|
2013-05-31 16:03:11 +06:00
|
|
|
aData: String): IXmlProcessingInstruction;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlProcessingInstruction.Create(FNames, FNames.GetID(aTarget), aData)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.CreateProcessingInstruction(aTargetID: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
const aData: String): IXmlProcessingInstruction;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlProcessingInstruction.Create(FNames, aTargetID, aData)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlDocument.CreateText(const aData: String): IXmlText;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlText.Create(FNames, aData)
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.DoCloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
var
|
|
|
|
aClone: TXmlDocument;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
aClone := TXmlDocument.Create(FNames);
|
|
|
|
Result := aClone;
|
|
|
|
if aDeep and Assigned(FChilds) and (FChilds.FCount > 0) then
|
|
|
|
for i := 0 to FChilds.FCount - 1 do
|
|
|
|
aClone.AppendChild(FChilds.FItems[i].CloneNode(True));
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlDocument.Get_BinaryXML: RawByteString;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aWriter: TRawByteStringBinaryXmlWriter;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
aWriter := TRawByteStringBinaryXmlWriter.Create(0, $10000);
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
|
|
|
FNames.SaveBinXml(aWriter);
|
|
|
|
SaveBinXml(aWriter);
|
|
|
|
aWriter.FlushBuf;
|
|
|
|
Result := aWriter.FData;
|
|
|
|
finally
|
|
|
|
aWriter.Free
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.Get_DocumentElement: IXmlElement;
|
|
|
|
var
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
aChild: TXmlNode;
|
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
aChilds := GetChilds;
|
|
|
|
for i := 0 to aChilds.FCount - 1 do begin
|
|
|
|
aChild := aChilds.FItems[i];
|
|
|
|
if aChild.Get_NodeType = NODE_ELEMENT then begin
|
|
|
|
Result := aChild.AsElement;
|
|
|
|
Exit
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
Result := nil;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.Get_NodeNameID: Integer;
|
|
|
|
begin
|
|
|
|
Result := FNames.FXmlDocumentNameID
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.Get_NodeType: Integer;
|
|
|
|
begin
|
|
|
|
Result := NODE_DOCUMENT
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.Get_PreserveWhiteSpace: Boolean;
|
|
|
|
begin
|
|
|
|
Result := FPreserveWhiteSpace;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlDocument.Get_Text: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
aChild: TXmlNode;
|
2013-05-31 16:03:11 +06:00
|
|
|
aChildText: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
i: Integer;
|
|
|
|
begin
|
|
|
|
Result := '';
|
|
|
|
aChilds := GetChilds;
|
|
|
|
for i := 0 to aChilds.FCount - 1 do begin
|
|
|
|
aChild := aChilds.FItems[i];
|
|
|
|
if aChild.Get_NodeType in [NODE_ELEMENT, NODE_TEXT, NODE_CDATA_SECTION] then begin
|
|
|
|
aChildText := aChild.Get_Text;
|
|
|
|
if aChildText <> '' then
|
|
|
|
if Result = '' then
|
|
|
|
Result := aChildText
|
|
|
|
else
|
|
|
|
Result := Result + ' ' + aChildText
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlDocument.GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.GetXML(anXml)
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlDocument.Load(aStream: TStream);
|
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
anXml: TAnsiStreamXmlSource;
|
|
|
|
aBinarySign: RawByteString;
|
|
|
|
aReader: TBinaryXmlReader;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
RemoveAllChilds;
|
|
|
|
RemoveAllAttrs;
|
|
|
|
if aStream.Size > BinXmlSignatureSize then begin
|
|
|
|
SetLength(aBinarySign, BinXmlSignatureSize);
|
|
|
|
aStream.ReadBuffer(aBinarySign[1], BinXmlSignatureSize);
|
|
|
|
if aBinarySign = BinXmlSignature then begin
|
|
|
|
FNames._Release;
|
|
|
|
FNames := TXmlNameTable.Create(4096);
|
|
|
|
FNames._AddRef;
|
2013-05-31 16:03:11 +06:00
|
|
|
aReader := TStreamBinaryXmlReader.Create(aStream, $10000);
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
|
|
|
FNames.LoadBinXml(aReader);
|
|
|
|
LoadBinXml(aReader);
|
|
|
|
finally
|
|
|
|
aReader.Free
|
|
|
|
end;
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
aStream.Position := aStream.Position - BinXmlSignatureSize;
|
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
anXml := TAnsiStreamXmlSource.Create(aStream, 1 shl 16);
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
2010-11-06 22:21:34 +02:00
|
|
|
GetChilds.ParseXML(anXml, FNames, FPreserveWhiteSpace);
|
2010-11-06 22:16:58 +02:00
|
|
|
finally
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Free
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlDocument.Load(const aFileName: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aFile: TFileStream;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
aFile := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyWrite, fmShareDenyWrite);
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
2010-11-06 22:21:34 +02:00
|
|
|
try
|
|
|
|
Load(aFile);
|
|
|
|
except
|
|
|
|
on E: Exception do begin
|
|
|
|
E.Message := format(SSimpleXmlError26, [E.Message, aFileName]);
|
|
|
|
raise;
|
|
|
|
end;
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
finally
|
|
|
|
aFile.Free
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlDocument.LoadBinaryXML(const anXml: RawByteString);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aReader: TRawByteStringBinaryXmlReader;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
RemoveAllChilds;
|
|
|
|
RemoveAllAttrs;
|
2013-05-31 16:03:11 +06:00
|
|
|
aReader := TRawByteStringBinaryXmlReader.Create(anXml);
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
|
|
|
FNames._Release;
|
|
|
|
FNames := TXmlNameTable.Create(4096);
|
|
|
|
FNames._AddRef;
|
|
|
|
FNames.LoadBinXml(aReader);
|
|
|
|
LoadBinXml(aReader);
|
|
|
|
finally
|
|
|
|
aReader.Free
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlDocument.LoadResource(aType, aName: PChar);
|
|
|
|
var
|
|
|
|
aRSRC: HRSRC;
|
|
|
|
aGlobal: HGLOBAL;
|
|
|
|
aSize: DWORD;
|
|
|
|
aPointer: Pointer;
|
|
|
|
aStream: TStringStream;
|
|
|
|
begin
|
|
|
|
aRSRC := FindResource(HInstance, aName, aType);
|
|
|
|
if aRSRC <> 0 then begin
|
|
|
|
aGlobal := Windows.LoadResource(HInstance, aRSRC);
|
|
|
|
aSize := SizeofResource(HInstance, aRSRC);
|
|
|
|
if (aGlobal <> 0) and (aSize <> 0) then begin
|
|
|
|
aPointer := LockResource(aGlobal);
|
|
|
|
if Assigned(aPointer) then begin
|
|
|
|
aStream := TStringStream.Create('');
|
|
|
|
try
|
|
|
|
aStream.WriteBuffer(aPointer^, aSize);
|
|
|
|
LoadXML(aStream.DataString);
|
|
|
|
finally
|
|
|
|
aStream.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlDocument.LoadXML(const anXml: String);
|
|
|
|
var
|
|
|
|
aSource: TStringXmlSource;
|
|
|
|
begin
|
|
|
|
RemoveAllChilds;
|
|
|
|
RemoveAllAttrs;
|
|
|
|
aSource := TStringXmlSource.Create(anXml);
|
|
|
|
try
|
|
|
|
GetChilds.ParseXML(aSource, FNames, FPreserveWhiteSpace);
|
|
|
|
finally
|
|
|
|
aSource.Free
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlDocument.LoadXML(const anXml: RawByteString);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aSource: TStringXmlSource;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if XmlIsInBinaryFormat(anXml) then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
LoadBinaryXML(anXml)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
RemoveAllChilds;
|
|
|
|
RemoveAllAttrs;
|
2013-05-31 16:03:11 +06:00
|
|
|
aSource := TStringXmlSource.Create(String(anXml));
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
|
|
|
GetChilds.ParseXML(aSource, FNames, FPreserveWhiteSpace);
|
|
|
|
finally
|
|
|
|
aSource.Free
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlDocument.NewDocument(const aVersion, anEncoding,
|
2013-05-31 16:03:11 +06:00
|
|
|
aRootElementName: String): IXmlElement;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := NewDocument(aVersion, anEncoding, FNames.GetID(aRootElementName));
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlDocument.NewDocument(const aVersion, anEncoding: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
aRootElementNameID: Integer): IXmlElement;
|
|
|
|
var
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
aRoot: TXmlElement;
|
|
|
|
e: String;
|
|
|
|
begin
|
|
|
|
aChilds := GetChilds;
|
2010-11-06 22:21:34 +02:00
|
|
|
aChilds.ClearNodes;
|
2010-11-06 22:16:58 +02:00
|
|
|
if anEncoding = '' then
|
|
|
|
e := DefaultEncoding
|
|
|
|
else
|
|
|
|
e := anEncoding;
|
2010-11-06 22:21:34 +02:00
|
|
|
aChilds.InsertNode(TXmlProcessingInstruction.Create(FNames, FNames.FXmlID,
|
2010-11-06 22:16:58 +02:00
|
|
|
'version="' + aVersion + '" encoding="' + e + '"'), 0);
|
|
|
|
aRoot := TXmlElement.Create(FNames, aRootElementNameID);
|
2010-11-06 22:21:34 +02:00
|
|
|
aChilds.InsertNode(aRoot, 1);
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := aRoot;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlDocument.Save(aStream: TStream);
|
|
|
|
var
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml: TStringBuilder;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Init;
|
2013-05-31 16:03:11 +06:00
|
|
|
GetXML(anXml);
|
|
|
|
if anXml.FLength > 0 then begin
|
|
|
|
aStream.WriteBuffer(anXml.FData[1], sizeof(Char)*anXml.FLength);
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlDocument.Save(const aFileName: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aFile: TFileStream;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if FileExists(aFileName) then begin
|
|
|
|
aFile := TFileStream.Create(aFileName, fmOpenWrite or fmShareDenyWrite);
|
|
|
|
aFile.Size := 0;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
aFile := TFileStream.Create(aFileName, fmCreate);
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
|
|
|
Save(aFile);
|
|
|
|
finally
|
|
|
|
aFile.Free
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlDocument.SaveBinary(aStream: TStream; anOptions: LongWord);
|
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aWriter: TBinaryXmlWriter;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
aWriter := TStreamBinrayXmlWriter.Create(aStream, anOptions, 65536);
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
|
|
|
FNames.SaveBinXml(aWriter);
|
|
|
|
SaveBinXml(aWriter);
|
|
|
|
finally
|
|
|
|
aWriter.Free
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlDocument.SaveBinary(const aFileName: String; anOptions: LongWord);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aFile: TFileStream;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
aFile := TFileStream.Create(aFileName, fmCreate or fmShareDenyWrite);
|
2010-11-06 22:16:58 +02:00
|
|
|
try
|
|
|
|
SaveBinary(aFile, anOptions);
|
|
|
|
finally
|
|
|
|
aFile.Free
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlDocument.Set_PreserveWhiteSpace(aValue: Boolean);
|
|
|
|
begin
|
|
|
|
FPreserveWhiteSpace := aValue;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlDocument.Set_Text(const aText: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aChilds: TXmlNodeList;
|
|
|
|
begin
|
|
|
|
aChilds := GetChilds;
|
2010-11-06 22:21:34 +02:00
|
|
|
aChilds.ClearNodes;
|
|
|
|
aChilds.InsertNode(TXmlText.Create(FNames, aText), 0);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlProcessingInstruction }
|
|
|
|
|
|
|
|
function TXmlProcessingInstruction.AsProcessingInstruction: IXmlProcessingInstruction;
|
|
|
|
begin
|
|
|
|
Result := Self
|
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TXmlProcessingInstruction.Create(aNames: TXmlNameTable;
|
2013-05-31 16:03:11 +06:00
|
|
|
aTargetID: Integer; const aData: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
inherited Create(aNames);
|
|
|
|
FTargetID := aTargetID;
|
|
|
|
FData := aData;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlProcessingInstruction.DoCloneNode(aDeep: Boolean): IXmlNode;
|
|
|
|
begin
|
|
|
|
Result := TXmlProcessingInstruction.Create(FNames, FTargetID, FData);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlProcessingInstruction.Get_NodeNameID: Integer;
|
|
|
|
begin
|
|
|
|
Result := FTargetID
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlProcessingInstruction.Get_NodeType: Integer;
|
|
|
|
begin
|
|
|
|
Result := NODE_PROCESSING_INSTRUCTION
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlProcessingInstruction.Get_Text: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := FData;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
procedure TXmlProcessingInstruction.GetXML(var anXml: TStringBuilder);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
anXml.Add('<?' + FNames.GetName(FTargetID));
|
2010-11-06 22:16:58 +02:00
|
|
|
if FData = '' then
|
2013-05-31 16:03:11 +06:00
|
|
|
GetAttrsXML(anXml)
|
2010-11-06 22:16:58 +02:00
|
|
|
else
|
2010-11-06 22:21:34 +02:00
|
|
|
anXml.Add(' ' + FData);
|
2013-05-31 16:03:11 +06:00
|
|
|
anXml.Add('?>');
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlProcessingInstruction.Get_Target: String;
|
|
|
|
begin
|
|
|
|
Result := FNames.GetName(FTargetID);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlProcessingInstruction.SetNodeNameID(aValue: Integer);
|
|
|
|
begin
|
|
|
|
FTargetID := aValue
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlProcessingInstruction.Set_Text(const aText: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FData := aText
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlStrSource }
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor TStringXmlSource.Create(const aSource: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FSource := aSource;
|
2013-05-31 16:03:11 +06:00
|
|
|
FSourcePtr := PChar(FSource);
|
2010-11-06 22:16:58 +02:00
|
|
|
FSourceEnd := FSourcePtr + Length(FSource);
|
|
|
|
if FSourcePtr = FSourceEnd then
|
|
|
|
CurChar := #0
|
|
|
|
else
|
|
|
|
CurChar := FSourcePtr^;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TStringXmlSource.EOF: Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := FSourcePtr = FSourceEnd
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TStringXmlSource.DoNext: Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
if FSourcePtr < FSourceEnd then
|
|
|
|
Inc(FSourcePtr);
|
|
|
|
if FSourcePtr = FSourceEnd then begin
|
|
|
|
Result := False;
|
|
|
|
CurChar := #0;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
Result := True;
|
|
|
|
CurChar := FSourcePtr^;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlSource }
|
|
|
|
|
|
|
|
procedure TXmlSource.NewToken;
|
|
|
|
begin
|
|
|
|
Inc(FTokenStackTop);
|
|
|
|
if FTokenStackTop < Length(FTokenStack) then begin
|
|
|
|
FToken := FTokenStack[FTokenStackTop];
|
|
|
|
FToken.Clear
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
SetLength(FTokenStack, FTokenStackTop + 1);
|
|
|
|
FToken := TXmlToken.Create;
|
|
|
|
FTokenStack[FTokenStackTop] := FToken;
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlSource.AcceptToken: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
SetLength(Result, FToken.FValuePtr - FToken.ValueStart);
|
2013-05-31 16:03:11 +06:00
|
|
|
if Length(Result) > 0 then begin
|
|
|
|
Move(FToken.ValueStart^, Result[1], Length(Result)*sizeof(Char));
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
DropToken;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function TXmlSource.Next: Boolean;
|
|
|
|
begin
|
|
|
|
Result := DoNext;
|
|
|
|
if Result then begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if (CurChar = ^M) or (CurChar = ^J) and (FPrevChar <> ^M) and (FPrevChar <> ^J) then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
Inc(FCurLine);
|
|
|
|
FCurPos := 0;
|
|
|
|
end
|
2013-05-31 16:03:11 +06:00
|
|
|
else if CurChar <> ^J then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
Inc(FCurPos);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:21:34 +02:00
|
|
|
FPrevChar := CurChar;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure TXmlSource.SkipBlanks;
|
|
|
|
begin
|
|
|
|
while not EOF and (CurChar <= ' ') do
|
|
|
|
Next;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// �� ����� - ������ ������ �����
|
|
|
|
// �� ������ - ������ ������, ������� �� �������� ���������� ��� ����
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlSource.ExpectXmlName: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
if not NameCanBeginWith(CurChar) then
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError11, [FCurLine, FCurPos]);
|
2010-11-06 22:16:58 +02:00
|
|
|
NewToken;
|
|
|
|
AppendTokenChar(CurChar);
|
|
|
|
while Next and NameCanContain(CurChar) do
|
|
|
|
AppendTokenChar(CurChar);
|
|
|
|
Result := AcceptToken;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// �� ����� - ������ ������ �����
|
|
|
|
// �� ������ - ������ ������, ������� �� �������� ���������� ��� �����
|
|
|
|
function TXmlSource.ExpectDecimalInteger: Integer;
|
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
s: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
e: Integer;
|
|
|
|
begin
|
|
|
|
NewToken;
|
|
|
|
while (CurChar >= '0') and (CurChar <= '9') do begin
|
|
|
|
AppendTokenChar(CurChar);
|
|
|
|
Next;
|
|
|
|
end;
|
|
|
|
s := AcceptToken;
|
|
|
|
if Length(s) = 0 then
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError12, [FCurLine, FCurPos]);
|
2010-11-06 22:16:58 +02:00
|
|
|
Val(s, Result, e);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function IsHexDigit(c: Char): Boolean;
|
|
|
|
begin
|
|
|
|
Result := (c >= '0') and (c <= '9') or (c >= 'A') and (c <= 'F') or (c >= 'a') and (c <= 'f')
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
// �� ����� - ������ ������ �����
|
|
|
|
// �� ������ - ������ ������, ������� �� �������� ���������� ���
|
|
|
|
// ����������������� �����
|
|
|
|
function TXmlSource.ExpectHexInteger: Integer;
|
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
s: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
e: Integer;
|
|
|
|
begin
|
|
|
|
NewToken;
|
2013-05-31 16:03:11 +06:00
|
|
|
while IsHexDigit(CurChar) do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
AppendTokenChar(CurChar);
|
|
|
|
Next;
|
|
|
|
end;
|
|
|
|
s := '$';
|
|
|
|
s := s + AcceptToken;
|
2013-05-31 16:03:11 +06:00
|
|
|
if Length(s) = 1 then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError13, [FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Val(s, Result, e);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// �� �����: "&"
|
|
|
|
// �� ������: ��������� �� ";"
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlSource.ExpectXmlEntity: Char;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
s: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if not Next then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError14, [FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
if CurChar = '#' then begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if not Next then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError12, [FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
if CurChar = 'x' then begin
|
|
|
|
Next;
|
2013-05-31 16:03:11 +06:00
|
|
|
Result := Char(ExpectHexInteger);
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
2013-05-31 16:03:11 +06:00
|
|
|
else begin
|
|
|
|
Result := Char(ExpectDecimalInteger);
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
ExpectChar(';');
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
s := ExpectXmlName;
|
|
|
|
ExpectChar(';');
|
2013-05-31 16:03:11 +06:00
|
|
|
if s = 'amp' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := '&'
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if s = 'quot' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := '"'
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if s = 'lt' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := '<'
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if s = 'gt' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := '>'
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if s = 'apos' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := ''''
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError15, [FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlSource.ExpectChar(aChar: Char);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if EOF or (CurChar <> aChar) then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError16, [aChar, FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Next;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlSource.ExpectText(aText: PChar);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
while aText^ <> #0 do begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if (CurChar <> aText^) or EOF then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError17, [aText, FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(aText);
|
|
|
|
Next;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// �� �����: ����������� �������
|
|
|
|
// �� ������: ������, ��������� �� ����������� ��������
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlSource.ExpectQuotedText(aQuote: Char): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
NewToken;
|
|
|
|
Next;
|
|
|
|
while not EOF and (CurChar <> aQuote) do begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if CurChar = '&' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
AppendTokenChar(ExpectXmlEntity)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else if CurChar = '<' then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError18, [FCurLine, FCurPos])
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
AppendTokenChar(CurChar);
|
|
|
|
Next;
|
|
|
|
end
|
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
if EOF then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SimpleXmlError19, [aQuote, FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Next;
|
|
|
|
Result := AcceptToken;
|
|
|
|
end;
|
2010-11-06 22:21:34 +02:00
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
procedure TXmlSource.ParseAttrs(aNode: TXmlNode);
|
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aName: String;
|
|
|
|
aValue: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
SkipBlanks;
|
|
|
|
while not EOF and NameCanBeginWith(CurChar) do begin
|
|
|
|
aName := ExpectXmlName;
|
|
|
|
SkipBlanks;
|
|
|
|
ExpectChar('=');
|
|
|
|
SkipBlanks;
|
2013-05-31 16:03:11 +06:00
|
|
|
if EOF then begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError20, [FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
if (CurChar = '''') or (CurChar = '"') then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aValue := ExpectQuotedText(CurChar)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SSimpleXmlError21, [FCurLine, FCurPos]);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
aNode.SetAttr(aName, aValue);
|
|
|
|
SkipBlanks;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function StrEquals(p1, p2: PChar; aLen: Integer): Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
while aLen > 0 do
|
|
|
|
if p1^ <> p2^ then begin
|
|
|
|
Result := False;
|
|
|
|
Exit
|
|
|
|
end
|
|
|
|
else if (p1^ = #0) or (p2^ = #0) then begin
|
|
|
|
Result := p1^ = p2^;
|
|
|
|
Exit
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
Inc(p1);
|
|
|
|
Inc(p2);
|
|
|
|
Dec(aLen);
|
|
|
|
end;
|
|
|
|
Result := True;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// �� �����: ������ ������ ������
|
|
|
|
// �� ������: ������, ��������� �� ��������� �������� ������������
|
2013-05-31 16:03:11 +06:00
|
|
|
function TXmlSource.ParseTo(aText: PChar): String;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aCheck: PChar;
|
|
|
|
p: PChar;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
NewToken;
|
|
|
|
aCheck := aText;
|
|
|
|
while not EOF do begin
|
|
|
|
if CurChar = aCheck^ then begin
|
|
|
|
Inc(aCheck);
|
|
|
|
Next;
|
|
|
|
if aCheck^ = #0 then begin
|
|
|
|
Result := AcceptToken;
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else if aCheck = aText then begin
|
|
|
|
AppendTokenChar(CurChar);
|
|
|
|
Next;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
p := aText + 1;
|
2013-05-31 16:03:11 +06:00
|
|
|
while (p < aCheck) and not StrEquals(p, aText, aCheck - p) do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(p);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
AppendTokenText(aText, p - aText);
|
2013-05-31 16:03:11 +06:00
|
|
|
if p < aCheck then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aCheck := p
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aCheck := aText;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
2010-11-06 22:21:34 +02:00
|
|
|
raise Exception.CreateFmt(SimpleXmlError22, [aText, FCurLine, FCurPos]);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlSource.AppendTokenChar(aChar: Char);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FToken.AppendChar(aChar);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlSource.AppendTokenText(aText: PChar; aCount: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FToken.AppendText(aText, aCount)
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlSource.DropToken;
|
|
|
|
begin
|
|
|
|
Dec(FTokenStackTop);
|
2013-05-31 16:03:11 +06:00
|
|
|
if FTokenStackTop >= 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
FToken := FTokenStack[FTokenStackTop]
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
FToken := nil
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TXmlSource.Create;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FTokenStackTop := -1;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TXmlSource.Destroy;
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
for i := 0 to Length(FTokenStack) - 1 do begin
|
2010-11-06 22:16:58 +02:00
|
|
|
FTokenStack[i].Free;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TXmlToken }
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlToken.AppendChar(aChar: Char);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aSaveLength: Integer;
|
|
|
|
begin
|
|
|
|
if FValuePtr >= FValueEnd then begin
|
|
|
|
aSaveLength := FValuePtr - FValueStart;
|
|
|
|
SetLength(FValueBuf, aSaveLength + 1);
|
2013-05-31 16:03:11 +06:00
|
|
|
FValueStart := PChar(FValueBuf);
|
2010-11-06 22:16:58 +02:00
|
|
|
FValuePtr := FValueStart + aSaveLength;
|
|
|
|
FValueEnd := FValueStart + System.Length(FValueBuf);
|
|
|
|
end;
|
|
|
|
FValuePtr^ := aChar;
|
|
|
|
Inc(FValuePtr);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TXmlToken.AppendText(aText: PChar; aCount: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aSaveLength: Integer;
|
|
|
|
begin
|
|
|
|
if (FValuePtr + aCount) > FValueEnd then begin
|
|
|
|
aSaveLength := FValuePtr - FValueStart;
|
|
|
|
SetLength(FValueBuf, aSaveLength + aCount);
|
2013-05-31 16:03:11 +06:00
|
|
|
FValueStart := PChar(FValueBuf);
|
2010-11-06 22:16:58 +02:00
|
|
|
FValuePtr := FValueStart + aSaveLength;
|
|
|
|
FValueEnd := FValueStart + System.Length(FValueBuf);
|
|
|
|
end;
|
2013-05-31 16:03:11 +06:00
|
|
|
Move(aText^, FValuePtr^, aCount*sizeof(Char));
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(FValuePtr, aCount);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TXmlToken.Clear;
|
|
|
|
begin
|
|
|
|
FValuePtr := FValueStart;
|
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TXmlToken.Create;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
SetLength(FValueBuf, 32);
|
2013-05-31 16:03:11 +06:00
|
|
|
FValueStart := PChar(FValueBuf);
|
2010-11-06 22:16:58 +02:00
|
|
|
FValuePtr := FValueStart;
|
|
|
|
FValueEnd := FValueStart + 32;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TXmlToken.Length: Integer;
|
|
|
|
begin
|
|
|
|
Result := FValuePtr - FValueStart;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function AnsiToUnicode(c: AnsiChar): WideChar;
|
|
|
|
begin
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, @c, 1, @Result, 1);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
{ TAnsiStreamXmlSource }
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor TAnsiStreamXmlSource.Create(aStream: TStream; aBufSize: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aSize: Integer;
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FStream := aStream;
|
|
|
|
FBufSize := aBufSize;
|
|
|
|
FBufStart := AllocMem(aBufSize);
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
FBufEnd := FBufStart;
|
|
|
|
FSize := aStream.Size;
|
2013-05-31 16:03:11 +06:00
|
|
|
if FSize = 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
CurChar := #0
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if FSize < FBufSize then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aSize := FSize
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aSize := FBufSize;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
FStream.ReadBuffer(FBufStart^, aSize);
|
|
|
|
FBufEnd := FBufStart + aSize;
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
Dec(FSize, aSize);
|
2013-05-31 16:03:11 +06:00
|
|
|
CurChar := Char(FBufPtr^);
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
destructor TAnsiStreamXmlSource.Destroy;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FreeMem(FBufStart);
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TAnsiStreamXmlSource.EOF: Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := (FBufPtr = FBufEnd) and (FSize = 0)
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TAnsiStreamXmlSource.DoNext: Boolean;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aSize: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if FBufPtr < FBufEnd then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Inc(FBufPtr);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
if FBufPtr = FBufEnd then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
if FSize = 0 then begin
|
|
|
|
Result := False;
|
|
|
|
CurChar := #0;
|
|
|
|
end
|
|
|
|
else begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if FSize < FBufSize then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aSize := FSize
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aSize := FBufSize;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
FStream.ReadBuffer(FBufStart^, aSize);
|
|
|
|
FBufEnd := FBufStart + aSize;
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
Dec(FSize, aSize);
|
|
|
|
Result := True;
|
2013-05-31 16:03:11 +06:00
|
|
|
CurChar := Char(FBufPtr^);
|
2010-11-06 22:16:58 +02:00
|
|
|
end
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
Result := True;
|
2013-05-31 16:03:11 +06:00
|
|
|
CurChar := Char(FBufPtr^);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
{ TStreamBinaryXmlReader }
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor TStreamBinaryXmlReader.Create(aStream: TStream; aBufSize: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FStream := aStream;
|
|
|
|
FRestSize := aStream.Size - aStream.Position;
|
|
|
|
FBufSize := aBufSize;
|
|
|
|
FBufStart := AllocMem(aBufSize);
|
|
|
|
FBufEnd := FBufStart;
|
|
|
|
FBufPtr := FBufEnd;
|
|
|
|
Read(FOptions, sizeof(FOptions));
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
destructor TStreamBinaryXmlReader.Destroy;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FreeMem(FBufStart);
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TStreamBinaryXmlReader.Read(var aBuf; aSize: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aBufRest: Integer;
|
2013-05-31 16:03:11 +06:00
|
|
|
aDst: PAnsiChar;
|
2010-11-06 22:16:58 +02:00
|
|
|
aBufSize: Integer;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if aSize > FRestSize then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
raise Exception.Create(SSimpleXmlError23);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
|
|
|
|
aBufRest := FBufEnd - FBufPtr;
|
|
|
|
if aSize <= aBufRest then begin
|
|
|
|
Move(FBufPtr^, aBuf, aSize);
|
|
|
|
Inc(FBufPtr, aSize);
|
|
|
|
Dec(FRestSize, aSize);
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
aDst := @aBuf;
|
|
|
|
Move(FBufPtr^, aDst^, aBufRest);
|
|
|
|
Inc(aDst, aBufRest);
|
|
|
|
FStream.ReadBuffer(aDst^, aSize - aBufRest);
|
|
|
|
Dec(FRestSize, aSize);
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
if FRestSize < FBufSize then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aBufSize := FRestSize
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aBufSize := FBufSize;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
FBufPtr := FBufStart;
|
|
|
|
FBufEnd := FBufStart + aBufSize;
|
2013-05-31 16:03:11 +06:00
|
|
|
if aBufSize > 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
FStream.ReadBuffer(FBufStart^, aBufSize);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
{ TRawByteStringBinaryXmlReader }
|
2010-11-06 22:16:58 +02:00
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor TRawByteStringBinaryXmlReader.Create(const aStr: RawByteString);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
2013-05-31 16:03:11 +06:00
|
|
|
aSig: array [1..BinXmlSignatureSize] of Byte;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FString := aStr;
|
|
|
|
FRestSize := Length(aStr);
|
2013-05-31 16:03:11 +06:00
|
|
|
if FRestSize > 0 then begin
|
|
|
|
FPtr := @FString[1];
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Read(aSig, BinXmlSignatureSize);
|
|
|
|
Read(FOptions, sizeof(FOptions));
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TRawByteStringBinaryXmlReader.Read(var aBuf; aSize: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if aSize > FRestSize then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
raise Exception.Create(SSimpleXmlError23);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Move(FPtr^, aBuf, aSize);
|
|
|
|
Inc(FPtr, aSize);
|
|
|
|
Dec(FRestSize, aSize);
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TBinXmlReader }
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TBinaryXmlReader.ReadAnsiString: AnsiString;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aLength: LongInt;
|
|
|
|
begin
|
|
|
|
aLength := ReadLongint;
|
|
|
|
if aLength = 0 then
|
|
|
|
Result := ''
|
|
|
|
else begin
|
|
|
|
SetLength(Result, aLength);
|
|
|
|
Read(Result[1], aLength);
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TBinaryXmlReader.ReadLongint: Longint;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
b: Byte;
|
|
|
|
begin
|
|
|
|
Result := 0;
|
|
|
|
Read(Result, 1);
|
|
|
|
if Result >= $80 then
|
|
|
|
if Result = $FF then
|
|
|
|
Read(Result, sizeof(Result))
|
|
|
|
else begin
|
|
|
|
Read(b, 1);
|
|
|
|
Result := (Result and $7F) shl 8 or b;
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TBinaryXmlReader.ReadVariant(var v: TVarData);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aDataType: Word;
|
|
|
|
aSize: Longint;
|
|
|
|
p: Pointer;
|
|
|
|
begin
|
|
|
|
VarClear(Variant(v));
|
|
|
|
aDataType := ReadLongint;
|
|
|
|
case aDataType of
|
|
|
|
varEmpty: ;
|
|
|
|
varNull: ;
|
|
|
|
varSmallint:
|
|
|
|
Read(v.VSmallint, sizeof(SmallInt));
|
|
|
|
varInteger:
|
|
|
|
Read(v.VInteger, sizeof(Integer));
|
|
|
|
varSingle:
|
|
|
|
Read(v.VSingle, sizeof(Single));
|
|
|
|
varDouble:
|
|
|
|
Read(v.VDouble, sizeof(Double));
|
|
|
|
varCurrency:
|
|
|
|
Read(v.VCurrency, sizeof(Currency));
|
|
|
|
varDate:
|
|
|
|
Read(v.VDate, sizeof(TDateTime));
|
|
|
|
varOleStr:
|
2013-05-31 16:03:11 +06:00
|
|
|
Variant(v) := ReadUnicodeString;
|
2010-11-06 22:16:58 +02:00
|
|
|
varBoolean:
|
|
|
|
Read(v.VBoolean, sizeof(WordBool));
|
|
|
|
varShortInt:
|
|
|
|
Read(v.VShortInt, sizeof(ShortInt));
|
|
|
|
varByte:
|
|
|
|
Read(v.VByte, sizeof(Byte));
|
|
|
|
varWord:
|
|
|
|
Read(v.VWord, sizeof(Word));
|
|
|
|
varLongWord:
|
|
|
|
Read(v.VLongWord, sizeof(LongWord));
|
|
|
|
varInt64:
|
|
|
|
Read(v.VInt64, sizeof(Int64));
|
|
|
|
varString:
|
|
|
|
Variant(v) := ReadAnsiString;
|
|
|
|
varArray + varByte:
|
|
|
|
begin
|
|
|
|
aSize := ReadLongint;
|
|
|
|
Variant(v) := VarArrayCreate([0, aSize - 1], varByte);
|
|
|
|
p := VarArrayLock(Variant(v));
|
|
|
|
try
|
|
|
|
Read(p^, aSize);
|
|
|
|
finally
|
|
|
|
VarArrayUnlock(Variant(v))
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
else
|
|
|
|
raise Exception.Create(SSimpleXmlError24);
|
|
|
|
end;
|
|
|
|
v.VType := aDataType;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TBinaryXmlReader.ReadUnicodeString: UnicodeString;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aLength: LongInt;
|
|
|
|
begin
|
|
|
|
aLength := ReadLongint;
|
2013-05-31 16:03:11 +06:00
|
|
|
if aLength = 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := ''
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:16:58 +02:00
|
|
|
else begin
|
|
|
|
SetLength(Result, aLength);
|
|
|
|
Read(Result[1], aLength*sizeof(WideChar));
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function TBinaryXmlReader.ReadXmlString: String;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if (FOptions and BINXML_USE_WIDE_CHARS) <> 0 then begin
|
|
|
|
Result := String(ReadUnicodeString)
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
Result := String(ReadAnsiString)
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
{ TStmXmlWriter }
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor TStreamBinrayXmlWriter.Create(aStream: TStream; anOptions: LongWord;
|
2010-11-06 22:16:58 +02:00
|
|
|
aBufSize: Integer);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FStream := aStream;
|
|
|
|
FOptions := anOptions;
|
|
|
|
FBufSize := aBufSize;
|
|
|
|
FBufStart := AllocMem(aBufSize);
|
|
|
|
FBufEnd := FBufStart + aBufSize;
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
Write(BinXmlSignature[1], BinXmlSignatureSize);
|
|
|
|
Write(FOptions, sizeof(FOptions));
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
destructor TStreamBinrayXmlWriter.Destroy;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
if FBufPtr > FBufStart then
|
|
|
|
FStream.WriteBuffer(FBufStart^, FBufPtr - FBufStart);
|
|
|
|
FreeMem(FBufStart);
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TStreamBinrayXmlWriter.Write(const aBuf; aSize: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aBufRest: Integer;
|
|
|
|
begin
|
|
|
|
aBufRest := FBufEnd - FBufPtr;
|
|
|
|
if aSize <= aBufRest then begin
|
|
|
|
Move(aBuf, FBufPtr^, aSize);
|
|
|
|
Inc(FBufPtr, aSize);
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if FBufPtr > FBufStart then begin
|
|
|
|
FStream.WriteBuffer(FBufStart^, FBufPtr - FBufStart);
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
end;
|
|
|
|
FStream.WriteBuffer(aBuf, aSize);
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TStrXmlWriter }
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
constructor TRawByteStringBinaryXmlWriter.Create(anOptions: LongWord; aBufSize: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FData := '';
|
|
|
|
FOptions := anOptions;
|
|
|
|
FBufSize := aBufSize;
|
|
|
|
FBufStart := AllocMem(aBufSize);
|
|
|
|
FBufEnd := FBufStart + aBufSize;
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
Write(BinXmlSignature[1], BinXmlSignatureSize);
|
|
|
|
Write(FOptions, sizeof(FOptions));
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
destructor TRawByteStringBinaryXmlWriter.Destroy;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
FreeMem(FBufStart);
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TRawByteStringBinaryXmlWriter.FlushBuf;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aPrevSize: Integer;
|
|
|
|
aSize: Integer;
|
|
|
|
begin
|
|
|
|
aPrevSize := Length(FData);
|
|
|
|
aSize := FBufPtr - FBufStart;
|
|
|
|
SetLength(FData, aPrevSize + aSize);
|
|
|
|
Move(FBufStart^, FData[aPrevSize + 1], aSize);
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TRawByteStringBinaryXmlWriter.Write(const aBuf; aSize: Integer);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aBufRest: Integer;
|
|
|
|
aPrevSize: Integer;
|
|
|
|
aBufSize: Integer;
|
|
|
|
begin
|
|
|
|
aBufRest := FBufEnd - FBufPtr;
|
|
|
|
if aSize <= aBufRest then begin
|
|
|
|
Move(aBuf, FBufPtr^, aSize);
|
|
|
|
Inc(FBufPtr, aSize);
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
aPrevSize := Length(FData);
|
|
|
|
aBufSize := FBufPtr - FBufStart;
|
|
|
|
SetLength(FData, aPrevSize + aBufSize + aSize);
|
|
|
|
if aBufSize > 0 then
|
|
|
|
Move(FBufStart^, FData[aPrevSize + 1], aBufSize);
|
|
|
|
Move(aBuf, FData[aPrevSize + aBufSize + 1], aSize);
|
|
|
|
FBufPtr := FBufStart;
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TBinXmlWriter }
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TBinaryXmlWriter.WriteAnsiString(const aValue: AnsiString);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aLength: LongInt;
|
|
|
|
begin
|
|
|
|
aLength := Length(aValue);
|
|
|
|
WriteLongint(aLength);
|
2013-05-31 16:03:11 +06:00
|
|
|
if aLength > 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Write(aValue[1], aLength);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TBinaryXmlWriter.WriteLongint(aValue: Longint);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
b: array [0..1] of Byte;
|
|
|
|
begin
|
|
|
|
if aValue < 0 then begin
|
|
|
|
b[0] := $FF;
|
|
|
|
Write(b[0], 1);
|
|
|
|
Write(aValue, SizeOf(aValue));
|
|
|
|
end
|
2013-05-31 16:03:11 +06:00
|
|
|
else if aValue < $80 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Write(aValue, 1)
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
2010-11-06 22:21:34 +02:00
|
|
|
else if aValue <= $7EFF then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
b[0] := (aValue shr 8) or $80;
|
|
|
|
b[1] := aValue and $FF;
|
|
|
|
Write(b, 2);
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
b[0] := $FF;
|
|
|
|
Write(b[0], 1);
|
|
|
|
Write(aValue, SizeOf(aValue));
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TBinaryXmlWriter.WriteVariant(const v: TVarData);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aSize: Integer;
|
|
|
|
p: Pointer;
|
|
|
|
begin
|
|
|
|
WriteLongint(v.VType);
|
|
|
|
case v.VType of
|
|
|
|
varEmpty: ;
|
|
|
|
varNull: ;
|
|
|
|
varSmallint:
|
|
|
|
Write(v.VSmallint, sizeof(SmallInt));
|
|
|
|
varInteger:
|
|
|
|
Write(v.VInteger, sizeof(Integer));
|
|
|
|
varSingle:
|
|
|
|
Write(v.VSingle, sizeof(Single));
|
|
|
|
varDouble:
|
|
|
|
Write(v.VDouble, sizeof(Double));
|
|
|
|
varCurrency:
|
|
|
|
Write(v.VCurrency, sizeof(Currency));
|
|
|
|
varDate:
|
|
|
|
Write(v.VDate, sizeof(TDateTime));
|
|
|
|
varOleStr:
|
2013-05-31 16:03:11 +06:00
|
|
|
WriteUnicodeString(Variant(v));
|
2010-11-06 22:16:58 +02:00
|
|
|
varBoolean:
|
|
|
|
Write(v.VBoolean, sizeof(WordBool));
|
|
|
|
varShortInt:
|
|
|
|
Write(v.VShortInt, sizeof(ShortInt));
|
|
|
|
varByte:
|
|
|
|
Write(v.VByte, sizeof(Byte));
|
|
|
|
varWord:
|
|
|
|
Write(v.VWord, sizeof(Word));
|
|
|
|
varLongWord:
|
|
|
|
Write(v.VLongWord, sizeof(LongWord));
|
|
|
|
varInt64:
|
|
|
|
Write(v.VInt64, sizeof(Int64));
|
|
|
|
varString:
|
2013-05-31 16:03:11 +06:00
|
|
|
WriteAnsiString(AnsiString(Variant(v)));
|
2010-11-06 22:16:58 +02:00
|
|
|
varArray + varByte:
|
|
|
|
begin
|
|
|
|
aSize := VarArrayHighBound(Variant(v), 1) - VarArrayLowBound(Variant(v), 1) + 1;
|
|
|
|
WriteLongint(aSize);
|
|
|
|
p := VarArrayLock(Variant(v));
|
|
|
|
try
|
|
|
|
Write(p^, aSize);
|
|
|
|
finally
|
|
|
|
VarArrayUnlock(Variant(v))
|
|
|
|
end
|
|
|
|
end;
|
|
|
|
else
|
|
|
|
raise Exception.Create(SSimpleXmlError25);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TBinaryXmlWriter.WriteUnicodeString(const aValue: UnicodeString);
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aLength: LongInt;
|
|
|
|
begin
|
|
|
|
aLength := Length(aValue);
|
|
|
|
WriteLongint(aLength);
|
2013-05-31 16:03:11 +06:00
|
|
|
if aLength > 0 then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Write(aValue[1], aLength*sizeof(WideChar));
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
procedure TBinaryXmlWriter.WriteXmlString(const aValue: String);
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if (FOptions and BINXML_USE_WIDE_CHARS) <> 0 then begin
|
|
|
|
WriteUnicodeString(UnicodeString(aValue))
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
WriteAnsiString(AnsiString(aValue))
|
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
DefaultNameTableImpl: TXmlNameTable = nil;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
function CreateXmlElement(const aName: String; const aNameTable: IXmlNameTable): IXmlElement;
|
2010-11-06 22:16:58 +02:00
|
|
|
var
|
|
|
|
aNameTableImpl: TXmlNameTable;
|
|
|
|
begin
|
|
|
|
if Assigned(aNameTable) then
|
|
|
|
aNameTableImpl := aNameTable.GetObject as TXmlNameTable
|
|
|
|
else
|
|
|
|
aNameTableImpl := DefaultNameTableImpl;
|
|
|
|
Result := TXmlElement.Create(aNameTableImpl, aNameTableImpl.GetID(aName));
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:21:34 +02:00
|
|
|
function CreateXmlNodeList: IXmlNodeList;
|
|
|
|
begin
|
|
|
|
Result := TXmlNodeList.Create(nil);
|
|
|
|
end;
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function CreateXmlDocument(
|
|
|
|
const aRootElementName: String;
|
|
|
|
const aVersion: String;
|
|
|
|
const anEncoding: String;
|
|
|
|
const aNames: IXmlNameTable): IXmlDocument;
|
|
|
|
var
|
|
|
|
aNameTable: TXmlNameTable;
|
|
|
|
s: String;
|
|
|
|
begin
|
2013-05-31 16:03:11 +06:00
|
|
|
if Assigned(aNames) then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aNameTable := aNames.GetObject as TXmlNameTable
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
aNameTable := DefaultNameTableImpl;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
|
|
|
if anEncoding = '' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
s := DefaultEncoding
|
2013-05-31 16:03:11 +06:00
|
|
|
end
|
|
|
|
else begin
|
2010-11-06 22:16:58 +02:00
|
|
|
s := anEncoding;
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
Result := TXmlDocument.Create(aNameTable);
|
2013-05-31 16:03:11 +06:00
|
|
|
if aRootElementName <> '' then begin
|
2010-11-06 22:16:58 +02:00
|
|
|
Result.NewDocument(aVersion, anEncoding, aRootElementName);
|
2013-05-31 16:03:11 +06:00
|
|
|
end;
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function LoadXmlDocumentFromXml(const anXml: String): IXmlDocument;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlDocument.Create(DefaultNameTableImpl);
|
2010-11-06 22:21:34 +02:00
|
|
|
Result.LoadXML(anXml);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function LoadXmlDocumentFromBinaryXML(const aBinaryXml: RawByteString): IXmlDocument;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlDocument.Create(DefaultNameTableImpl);
|
2013-05-31 16:03:11 +06:00
|
|
|
Result.LoadBinaryXML(aBinaryXml);
|
2010-11-06 22:16:58 +02:00
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function LoadXmlDocument(aStream: TStream): IXmlDocument;
|
|
|
|
begin
|
|
|
|
Result := TXmlDocument.Create(DefaultNameTableImpl);
|
|
|
|
Result.Load(aStream);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function LoadXmlDocument(const aFileName: String): IXmlDocument; overload;
|
2010-11-06 22:16:58 +02:00
|
|
|
begin
|
|
|
|
Result := TXmlDocument.Create(DefaultNameTableImpl);
|
|
|
|
Result.Load(aFileName);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
function LoadXmlDocument(aResType, aResName: PChar): IXmlDocument; overload;
|
|
|
|
begin
|
|
|
|
Result := TXmlDocument.Create(DefaultNameTableImpl);
|
|
|
|
Result.LoadResource(aResType, aResName);
|
|
|
|
end;
|
|
|
|
|
2013-05-31 16:03:11 +06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function AppendChildNodeFromXml(const aParentNode: IXmlNode; const anXml: String): IXmlNode;
|
|
|
|
begin
|
|
|
|
Result := LoadXmlDocumentFromXml(anXml).DocumentElement.CloneNode(true);
|
|
|
|
aParentNode.AppendChild(Result);
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-11-06 22:16:58 +02:00
|
|
|
initialization
|
|
|
|
DefaultNameTableImpl := TXmlNameTable.Create(4096);
|
|
|
|
DefaultNameTable := DefaultNameTableImpl;
|
|
|
|
finalization
|
|
|
|
DefaultNameTable := nil;
|
|
|
|
DefaultNameTableImpl := nil;
|
|
|
|
end.
|