598 lines
16 KiB
ObjectPascal
598 lines
16 KiB
ObjectPascal
unit uROOpenXMLImpl;
|
|
|
|
{----------------------------------------------------------------------------}
|
|
{ RemObjects SDK Library - Core Library }
|
|
{ }
|
|
{ compiler: Delphi 5 and up, Kylix 2 and up }
|
|
{ platform: Win32, Linux }
|
|
{ }
|
|
{ (c)opyright RemObjects Software. all rights reserved. }
|
|
{ }
|
|
{ Using this code requires a valid license of the RemObjects SDK }
|
|
{ which can be obtained at http://www.remobjects.com. }
|
|
{----------------------------------------------------------------------------}
|
|
|
|
{$I RemObjects.inc}
|
|
|
|
interface
|
|
|
|
uses Classes, uROXDOM_2_3, Variants, uROXMLIntf;
|
|
|
|
type
|
|
TROOpenXMLDocument = class;
|
|
{ TROOpenXMLNode }
|
|
TROOpenXMLNode = class(TInterfacedObject, IXMLNode)
|
|
private
|
|
fNode : TDOMNode;
|
|
fDoc: TROOpenXMLDocument;
|
|
//function GetNodesByAttribute(const anAttributeName, anAttributeValue: widestring): IXMLNodeList;
|
|
|
|
protected
|
|
function GetName : widestring;
|
|
function GetLocalName : widestring;
|
|
function GetRef : pointer;
|
|
function GetParent : IXMLNode;
|
|
|
|
function GetValue : Variant;
|
|
procedure SetValue(const Value : Variant);
|
|
|
|
function GetasString: widestring;
|
|
procedure SetasString(const Value: widestring);
|
|
|
|
function GetXML : widestring;
|
|
|
|
function GetAttributes(Index : integer) : IXMLNode;
|
|
function GetAttributeCount : integer;
|
|
|
|
function GetChildren(Index : integer) : IXMLNode;
|
|
function GetChildrenCount : integer;
|
|
|
|
function Add(const aNodeName : widestring; aNameSpaceURI: widestring = '') : IXMLNode;
|
|
function AddAttribute(const anAttributeName : widestring; const anAttributeValue : Variant) : IXMLNode; overload;
|
|
function AddAttribute(const anAttributeName : widestring; const anAttributeString: widestring) : IXMLNode; overload;
|
|
function AddXml(const Xml: WideString): IXMLNode;
|
|
|
|
procedure Delete(Index : integer);
|
|
procedure Remove(const aNode : IXMLNode);
|
|
|
|
function GetAttributeByName(const anAttributeName : widestring) : IXMLNode;
|
|
function GetAttributeValue(const anAttributeName : widestring; DefaultValue : Variant) : Variant;
|
|
function GetAttributeAsString(const anAttributeName : widestring; DefaultValue : widestring) : widestring;
|
|
|
|
function GetNodeByName(const aNodeName : widestring) : IXMLNode;
|
|
function GetNodeValue(const aNodeName : widestring; const Default : Variant) : Variant;
|
|
|
|
function GetNodesByName(const aNodeName : widestring) : IXMLNodeList;
|
|
|
|
function GetNodeByAttribute(const anAttributeName, anAttributeValue : widestring) : IXMLNode;
|
|
|
|
function GetFirstChild: IXMLNode;
|
|
function GetNextSibling: IXMLNode;
|
|
function GetNamespaceURI: WideString;
|
|
function GetDocument: IXMLDocument;
|
|
|
|
public
|
|
constructor Create(const aNode : TDOMNode; aDoc: TROOpenXMLDocument);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
{ TROOpenXMLNodeList }
|
|
TROOpenXMLNodeList = class(TInterfacedObject, IXMLNodeLIst)
|
|
private
|
|
fNodeList : TdomNodeList;
|
|
fDoc: TROOpenXMLDocument;
|
|
|
|
protected
|
|
function GetNodes(Index : integer) : IXMLNode;
|
|
function GetCount : integer;
|
|
|
|
public
|
|
constructor Create(const aNodeList : TdomNodeList; aDoc: TROOpenXMLDocument);
|
|
end;
|
|
|
|
{ TROOpenXMLDocument }
|
|
TROOpenXMLDocument = class(TInterfacedObject, IXMLDocument)
|
|
private
|
|
fDocument : TDOMDocument;
|
|
fDOMImpl : TDomImplementation;
|
|
|
|
protected
|
|
function GetDocumentNode : IXMLNode;
|
|
|
|
function GetEncoding : TXMLEncoding;
|
|
|
|
procedure New(aDocumentName : widestring = ''; anEncoding : TXMLEncoding = xeUTF8);
|
|
|
|
procedure SaveToStream(aStream : TStream);
|
|
procedure SaveToFile(const aFileName : string);
|
|
procedure LoadFromStream(aStream : TStream);
|
|
procedure LoadFromFile(const aFileName : string);
|
|
function GetXml:widestring;
|
|
procedure SetXML(const Value : widestring);
|
|
|
|
function Transform(const XSL : string) : string;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
end;
|
|
|
|
{ Misc. for OpenXML }
|
|
function DOMNodeToString(aDOMNode : TdomNode; aDOMImplementation : TDomImplementation = NIL) : string;
|
|
function DOMNodeToWidestring(aDOMNode : TdomNode; aDOMImplementation : TDomImplementation = NIL) : widestring;
|
|
|
|
implementation
|
|
|
|
uses uRORes, uROClasses, SysUtils;
|
|
|
|
function DOMNodeToString(aDOMNode : TdomNode; aDOMImplementation : TDomImplementation = NIL) : string;
|
|
var domimpl : TDOMImplementation;
|
|
parser : TDomToXmlParser;
|
|
begin
|
|
if (aDOMImplementation=NIL)
|
|
then domimpl := TDomImplementation.Create(NIL)
|
|
else domimpl := aDOMImplementation;
|
|
|
|
parser := TDomToXmlParser.Create(NIL);
|
|
|
|
try
|
|
parser.DOMImpl := domimpl;
|
|
parser.writeToString(aDOMNode, XMLEncodingStr[xeUTF8], result);
|
|
finally
|
|
parser.Free;
|
|
if (aDOMImplementation=NIL) then domimpl.Free;
|
|
end;
|
|
end;
|
|
|
|
function DOMNodeToWidestring(aDOMNode : TdomNode; aDOMImplementation : TDomImplementation = NIL) : widestring;
|
|
var domimpl : TDOMImplementation;
|
|
parser : TDomToXmlParser;
|
|
begin
|
|
if (aDOMImplementation=NIL)
|
|
then domimpl := TDomImplementation.Create(NIL)
|
|
else domimpl := aDOMImplementation;
|
|
|
|
parser := TDomToXmlParser.Create(NIL);
|
|
|
|
try
|
|
parser.DOMImpl := domimpl;
|
|
parser.writeToWideString(aDOMNode, result);
|
|
finally
|
|
parser.Free;
|
|
if (aDOMImplementation=NIL) then domimpl.Free;
|
|
end;
|
|
end;
|
|
|
|
{ TROOpenXMLNode }
|
|
|
|
constructor TROOpenXMLNode.Create(const aNode : TDOMNode; aDoc: TROOpenXMLDocument);
|
|
begin
|
|
if not Assigned(aNode)
|
|
then RaiseError(err_DOMElementIsNIL, []);
|
|
|
|
inherited Create;
|
|
|
|
fDoc := adoc;
|
|
fNode := aNode;
|
|
end;
|
|
|
|
destructor TROOpenXMLNode.Destroy;
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
function TROOpenXMLNode.Add(const aNodeName: widestring; aNameSpaceURI: widestring = ''): IXMLNode;
|
|
var node : TDOMNode;
|
|
begin
|
|
if aNameSpaceURI = '' then
|
|
node := fNode.ownerDocument.createElement(aNodeName)
|
|
else
|
|
node := fNode.ownerDocument.createElementNS(aNameSpaceURI, aNodeName);
|
|
fNode.appendChild(node);
|
|
|
|
result := TROOpenXMLNode.Create(node, fDoc);
|
|
end;
|
|
|
|
procedure TROOpenXMLNode.Delete(Index: integer);
|
|
begin
|
|
fNode.removeChild(fNode.childNodes.item(Index));
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetAttributes(Index : integer): IXMLNode;
|
|
begin
|
|
result := TROOpenXMLNode.Create(fNode.attributes.item(Index), fDoc);
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetChildren(Index : integer): IXMLNode;
|
|
begin
|
|
result := TROOpenXMLNode.Create(fNode.childNodes.item(Index), fDoc);
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetName: widestring;
|
|
begin
|
|
result := fNode.nodeName;
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetValue: Variant;
|
|
begin
|
|
result := fNode.textContent;
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetXML: widestring;
|
|
begin
|
|
DOMNodeToWidestring(fNode, fdoc.fDOMImpl);
|
|
end;
|
|
|
|
procedure TROOpenXMLNode.Remove(const aNode: IXMLNode);
|
|
begin
|
|
fNode.removeChild(TdomNode(aNode.Ref));
|
|
end;
|
|
|
|
procedure TROOpenXMLNode.SetValue(const Value: Variant);
|
|
var textnode : TdomNode;
|
|
begin
|
|
if (fNode.childNodes.length=1) and (fNode.childNodes.item(0).nodeName='#text')
|
|
then fNode.removeChild(fNode.childNodes.item(0));
|
|
|
|
textnode := fNode.ownerDocument.createTextNode(Value);
|
|
fNode.appendChild(textnode)
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetasString: widestring;
|
|
begin
|
|
Result:=fNode.textContent;
|
|
end;
|
|
|
|
procedure TROOpenXMLNode.SetasString(const Value: widestring);
|
|
var textnode : TdomNode;
|
|
begin
|
|
if (fNode.childNodes.length=1) and (fNode.childNodes.item(0).nodeName='#text')
|
|
then fNode.removeChild(fNode.childNodes.item(0));
|
|
|
|
textnode := fNode.ownerDocument.createTextNode(Value);
|
|
fNode.appendChild(textnode)
|
|
end;
|
|
|
|
|
|
function TROOpenXMLNode.GetNodeByName(const aNodeName: widestring): IXMLNode;
|
|
var i : integer;
|
|
nme : string;
|
|
begin
|
|
result := NIL;
|
|
|
|
with fNode.childNodes do
|
|
for i := 0 to (length-1) do begin
|
|
nme := item(i).nodeName;
|
|
if (nme=aNodeName) then begin
|
|
result := TROOpenXMLNode.Create(item(i), fDoc);
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{function TROOpenXMLNode.GetNodesByAttribute(const anAttributeName, anAttributeValue: widestring): IXMLNodeList;
|
|
//var node : TdomNodeList;
|
|
begin
|
|
RaiseError(err_NotImplemented, []);
|
|
end;}
|
|
|
|
function TROOpenXMLNode.GetNodesByName(const aNodeName: widestring): IXMLNodeList;
|
|
var //i : integer;
|
|
list : TdomNodeList;
|
|
begin
|
|
result := NIL;
|
|
|
|
list := (fNode as TdomElement).getElementsByTagName(aNodeName);
|
|
if (list<>NIL)
|
|
then result := TROOpenXMLNodeList.Create(list, fDoc)
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetAttributeCount: integer;
|
|
begin
|
|
result := fNode.attributes.length
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetChildrenCount: integer;
|
|
begin
|
|
result := fNode.childNodes.length
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetRef: pointer;
|
|
begin
|
|
result := fNode;
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetLocalName: widestring;
|
|
begin
|
|
result := fNode.nodeName
|
|
end;
|
|
|
|
function TROOpenXMLNode.AddAttribute(const anAttributeName : widestring;
|
|
const anAttributeValue : Variant) : IXMLNode;
|
|
var attr : TdomNode;
|
|
begin
|
|
attr := fNode.ownerDocument.createAttribute(anAttributeName);
|
|
attr.nodeValue := anAttributeValue;
|
|
fNode.attributes.setNamedItem(attr);
|
|
|
|
result := TROOpenXMLNode.Create(attr, fDoc);
|
|
end;
|
|
|
|
function TROOpenXMLNode.AddAttribute(const anAttributeName: widestring;
|
|
const anAttributeString: widestring): IXMLNode;
|
|
var attr : TdomNode;
|
|
begin
|
|
attr := fNode.ownerDocument.createAttribute(anAttributeName);
|
|
attr.nodeValue := anAttributeString;
|
|
fNode.attributes.setNamedItem(attr);
|
|
|
|
result := TROOpenXMLNode.Create(attr, fDoc);
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetParent: IXMLNode;
|
|
begin
|
|
result := TROOpenXMLNode.Create(fNode.ParentNode, fdoc)
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetAttributeByName(
|
|
const anAttributeName: widestring): IXMLNode;
|
|
var node : TDomNode;
|
|
begin
|
|
result := NIL;
|
|
if fNode.attributes = nil then exit;
|
|
node := fNode.attributes.getNamedItem(anAttributeName);
|
|
|
|
if (node<>NIL)
|
|
then result := TROOpenXMLNode.Create(node, fDoc);
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetNodeByAttribute(const anAttributeName,
|
|
anAttributeValue: widestring): IXMLNode;
|
|
var i : integer;
|
|
begin
|
|
result := NIL;
|
|
if fNode.attributes = nil then exit;
|
|
|
|
for i := 0 to (fNode.attributes.length-1) do
|
|
with fNode.attributes.item(i) do
|
|
if (nodeName=anAttributeName) and (nodeValue=anAttributeValue) then begin
|
|
result := TROOpenXMLNode.Create(fNode.attributes.item(i), fDoc);
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetAttributeValue(
|
|
const anAttributeName: widestring; DefaultValue: Variant): Variant;
|
|
var attr : IXMLNode;
|
|
begin
|
|
attr := GetAttributeByName(anAttributeName);
|
|
if (attr<>NIL) then
|
|
result := attr.Value
|
|
else
|
|
result := DefaultValue;
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetAttributeAsString(const anAttributeName: widestring;
|
|
DefaultValue: widestring): widestring;
|
|
var attr : IXMLNode;
|
|
begin
|
|
attr := GetAttributeByName(anAttributeName);
|
|
if (attr<>NIL) then
|
|
result := attr.Value
|
|
else
|
|
result := DefaultValue;
|
|
end;
|
|
|
|
|
|
|
|
function TROOpenXMLNode.GetNodeValue(const aNodeName: widestring;
|
|
const Default: Variant): Variant;
|
|
var node : IXMLNode;
|
|
begin
|
|
node := GetNodeByName(aNodeName);
|
|
if (node=NIL) then result := Default
|
|
else result := node.Value
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetFirstChild: IXMLNode;
|
|
var node : TDomNode;
|
|
begin
|
|
result := NIL;
|
|
node := fNode.firstChild;
|
|
|
|
if (node<>NIL)
|
|
then result := TROOpenXMLNode.Create(node, fDoc);
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetNextSibling: IXMLNode;
|
|
var node : TDomNode;
|
|
begin
|
|
result := NIL;
|
|
node := fNode.nextSibling;
|
|
|
|
if (node<>NIL)
|
|
then result := TROOpenXMLNode.Create(node, fDoc);
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetNamespaceURI: WideString;
|
|
begin
|
|
Result := fNode.namespaceURI;
|
|
end;
|
|
|
|
function TROOpenXMLNode.AddXml(const Xml: WideString): IXMLNode;
|
|
begin
|
|
end;
|
|
|
|
function TROOpenXMLNode.GetDocument: IXMLDocument;
|
|
begin
|
|
result := fDoc;
|
|
end;
|
|
|
|
{ TROOpenXMLNodeList }
|
|
|
|
constructor TROOpenXMLNodeList.Create(const aNodeList: TdomNodeList; aDoc: TROOpenXMLDocument);
|
|
begin
|
|
if not Assigned(aNodeList)
|
|
then RaiseError(err_DOMElementIsNIL, []);
|
|
|
|
inherited Create;
|
|
|
|
fDoc := aDoc;
|
|
fNodeList := aNodeList;
|
|
end;
|
|
|
|
function TROOpenXMLNodeList.GetCount: integer;
|
|
begin
|
|
result := fNodeList.length
|
|
end;
|
|
|
|
function TROOpenXMLNodeList.GetNodes(Index: integer): IXMLNode;
|
|
begin
|
|
result := TROOpenXMLNode.Create(fNodeList.item(Index), fDoc);
|
|
end;
|
|
|
|
{ TROOpenXMLDocument }
|
|
|
|
constructor TROOpenXMLDocument.Create;
|
|
begin
|
|
fDOMImpl := TDomImplementation.Create(NIL);
|
|
fDocument := fDOMImpl.createDocument('XMLDOC', NIL);
|
|
end;
|
|
|
|
destructor TROOpenXMLDocument.Destroy;
|
|
begin
|
|
fDOMImpl.freeDocument(fDocument);
|
|
fDOMImpl.Free;
|
|
|
|
inherited;
|
|
end;
|
|
|
|
function TROOpenXMLDocument.GetDocumentNode: IXMLNode;
|
|
begin
|
|
result := TROOpenXMLNode.Create(fDocument.documentElement, self)
|
|
end;
|
|
|
|
function TROOpenXMLDocument.GetEncoding: TXMLEncoding;
|
|
begin
|
|
result := xeUTF8
|
|
{ ToDo: for now, obtain the real encoding later ;-) }
|
|
end;
|
|
|
|
function TROOpenXMLDocument.GetXml: widestring;
|
|
var
|
|
parser : TDomToXmlParser;
|
|
begin
|
|
parser := TDomToXmlParser.Create(NIL);
|
|
|
|
try
|
|
parser.DOMImpl := fDOMImpl;
|
|
parser.writeToWideString(fDocument.documentElement, result);
|
|
finally
|
|
parser.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TROOpenXMLDocument.LoadFromFile(const aFileName: string);
|
|
var //domimpl : TDOMImplementation;
|
|
parser : TXmlToDomParser;
|
|
begin
|
|
New('');
|
|
parser := TXmlToDomParser.Create(NIL);
|
|
try
|
|
parser.DOMImpl := fDOMImpl;
|
|
|
|
fDocument := parser.fileToDom(aFileName);
|
|
finally
|
|
parser.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TROOpenXMLDocument.LoadFromStream(aStream: TStream);
|
|
var //domimpl : TDOMImplementation;
|
|
folddoc : TdomDocument;
|
|
parser : TXmlToDomParser;
|
|
begin
|
|
New('');
|
|
parser := TXmlToDomParser.Create(NIL);
|
|
try
|
|
parser.DOMImpl := fDOMImpl;
|
|
|
|
fOldDoc := fdocument;
|
|
fDocument := parser.streamToDom(aStream);
|
|
fOldDoc.domImplementation.freeDocument(fOldDoc);
|
|
finally
|
|
parser.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TROOpenXMLDocument.New(aDocumentName : widestring = ''; anEncoding : TXMLEncoding = xeUTF8);
|
|
var docel : TdomNode;
|
|
begin
|
|
fDocument.clear;
|
|
|
|
if (aDocumentName<>'') then begin
|
|
docel := fDocument.createElement(aDocumentName);
|
|
fDocument.appendChild(docel)
|
|
end;
|
|
end;
|
|
|
|
procedure TROOpenXMLDocument.SaveToFile(const aFileName: string);
|
|
var //domimpl : TDOMImplementation;
|
|
parser : TDomToXmlParser;
|
|
fstream : TFileStream;
|
|
begin
|
|
fstream := NIL;
|
|
parser := TDomToXmlParser.Create(NIL);
|
|
|
|
try
|
|
fstream := TFileStream.Create(aFileName, fmCreate);
|
|
parser.DOMImpl := fDOMImpl;
|
|
|
|
parser.writeToStream(fDocument.documentElement, 'UTF-8', fstream);
|
|
finally
|
|
parser.Free;
|
|
fstream.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TROOpenXMLDocument.SaveToStream(aStream: TStream);
|
|
var //domimpl : TDOMImplementation;
|
|
parser : TDomToXmlParser;
|
|
//fstream : TFileStream;
|
|
begin
|
|
//fstream := NIL;
|
|
parser := TDomToXmlParser.Create(NIL);
|
|
|
|
try
|
|
parser.DOMImpl := fDOMImpl;
|
|
parser.writeToStream(fDocument.documentElement, 'UTF-8', aStream);
|
|
finally
|
|
parser.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TROOpenXMLDocument.SetXML(const Value: widestring);
|
|
var
|
|
ss: TXmlToDomParser;
|
|
fOldDoc: TdomDocument;
|
|
begin
|
|
New('');
|
|
ss := TXmlToDomParser.Create(NIL);
|
|
try
|
|
ss.DOMImpl := fDOMImpl;
|
|
|
|
fOldDoc := fdocument;
|
|
fDocument := ss.wideStringToDom(value);
|
|
fOldDoc.Free;
|
|
finally
|
|
ss.Free;
|
|
end;
|
|
end;
|
|
|
|
function TROOpenXMLDocument.Transform(const XSL: string): string;
|
|
begin
|
|
RaiseError(err_NotImplemented, []);
|
|
end;
|
|
|
|
end.
|