I want to do this:
Read a XML file-> Save this file but if the Tag is <SQL> then run this SQl
and save the result from a Clientdataset XML in the output file....
Input:
...
<|SQL= select....>
Output
... (Same as in Input File=
... <SQL=select...>
< Resultset>
....
</Resultset>
What the best way ? Use SAXXMLReader ? and then SAXDocumentwriter? And how
do they work together ?
Do I need the "handler" components as well?
Any hints ?
Thanx
Holger
Actually the packages was written by many people-- I am just a contributor.
See contributors.txt for more info...
> <|SQL= select....>
Is this really in the input? It is not well formed.
> What the best way ? Use SAXXMLReader ? and then SAXDocumentwriter? And how
> do they work together ? Do I need the "handler" components as well?
Okay, this is actually a pretty advanced task. For starters I would do
something like:
Drop down a TSAXXMLReader, TSAXFilter, TSAXDocumentWriter. Then set the
TSAXXMLReader's Content, Decl, DTD, and Lexical handlers to the TSAXFilter.
Then set the TSAXFilter's Content, Decl, DTD, and Lexical handlers to the
TSAXDocumentWriter. This sets up a SAX filter chain with all of the output
going to the TSAXDocumentWriter.
Now add an OnStartElement event to the TSAXFilter. Add code to check if
LocalName = 'SQL', then you want to filter the elements from the output. So
you can do one of two things-- set filtered to true for all of the sub
elements (this is probably safest) or simply try to disconnect the document
writer until you reach the corresponding end element.
procedure TForm1.SAXFilter1StartElement(Sender: TObject; var NamespaceURI,
LocalName, QName: WideString; var Atts: IAttributes;
var Filtered: Boolean);
begin
// Set a flag
if (LocalName = 'SQL') then
FInSQL:= True;
// Filter the SQL elements
Filtered:= FInSQL;
end;
procedure TForm1.SAXFilter1EndElement(Sender: TObject; var NamespaceURI,
LocalName, QName: WideString; var Filtered: Boolean);
begin
// Filter the SQL elements
Filtered:= FInSQL;
// Set a flag
if (LocalName = 'SQL') then
FInSQL:= False;
end;
That should allow you to strip out the SQL blocks. Getting the resultset is
easy, but saving it means a little more hand coding. If you have it as a
stream, you might be able to just write to the Stream property of the
DocumentWriter-- but I am not positive.
HTH,
--
Jeff Rafter
Defined Systems
http://www.defined.net
XML Development and Developer Web Hosting
Yes, I know, so I meant "distributed by ..."
> > <|SQL= select....>
No, the input is indeed a long XML Document with many of this regions:
<SUBSECTOR ID="1" NAME="yyy">
<Query>
<DATABASE PWD="password" DRIVER="ORACLE" User="test"
Server="servername"/>
<SQL><![CDATA[select * from table]]></SQL>
<RESULTSET>
</RESULTSET>
</Query>
</SUBSECTOR>
And in the "Resultset" I want to copy the Clientdataset XML.
I'm now going to build the output file in a stringlist with OnStartElement
and OnEndElement.
I just retrieve the original data and write it in the stringlist.
That works , but how Do I get a Element like :
<Name>My Name </Name>
? I just get the begin and end element event. But how do I get the data ??
Another Problem occured on another computer. The "vendor list" from the
SaxXMLReader Component is empty.
I've set this on my computer to MSXML and copied the source, it compiles and
run fine. But when I open the form at design time it say "Invalid vendor".
When I run the "select Vendor Demo" there is MSXML in the list, the DLL is
there and we registered it (again).
Any Idea about this ?
Best regards
Holger
Comp
Holger
I am not sure what you mean here.
> I just retrieve the original data and write it in the stringlist.
> That works , but how Do I get a Element like :
> <Name>My Name </Name>
>
> ? I just get the begin and end element event. But how do I get the data ??
The data will be sent back in a characters event. So inside there do
something like:
procedure TForm1.SAXFilter1Characters(Sender: TObject; var PCh: WideString;
var Filtered: Boolean);
begin
if (FIsSQL) then
FSQLData:= FSQLData + PCh;
end;
From the help:
"The Parser will call this method to report each chunk of character data.
SAX parsers may return all contiguous character data in a single chunk, or
they may split it into several chunks; however, all of the characters in any
single event must come from the same external entity so that the Locator
provides useful information."
http://xml.defined.net/SAX/docs/SAX/IContentHandler.html#characters
That is why I did the SQLData field. Usually if you are collecting
OnCharacters events it is best to append in that manner. So, you can set
FSQLData:= ''; in the StartElement and actually deal with the data in the
EndElement (assuming you have no sub-elements as shown in your sample).
Cheers,