VerySimpleXML – a lightweight Delphi XML reader and writer
There are lot of possibilities if you’re in need to parse or write XML files:
- use TXMLDocument (the MSXML wrapper)
- or use xml components like OmniXML, NativeXml, ADOM, SAX, libxml2, DIXml, fcl-XML, Fast XMLParser, SimpleXML
Now here comes another one: VerySimpleXML – a lightweight, one-unit XML reader/writer in under 500 600 lines of code. Use it for small well-formed XML files (like configuration files, etc.).
Download verysimplexml-v1.1.zip (7kb)
Download verysimplexml-v1.0.zip (7kb)
What’s new:
v1.1 – 2012/05/01
changed class name to reflect unit naming (class is now called
TXmlVerySimple instead TVerySimpleXml)
- it uses TStreamReader to read line by line instead of reading the
whole file at once (this allows parsing of big xml files with little
additional memory)
- automatically escapes/unescapes not allowed chars (>, <, ", &), thus
removes the most-hated "- escaping introduced in v1.0
Some usage examples:
uses Xml.VerySimple; var Xml: TXmlVerySimple; Node, Child: TXmlNode; begin Xml := TXmlVerySimple.Create; Xml.LoadFromFile('example.xml'); Xml.Root.Find('book', 'id', 'bk102').Find('author').Text := 'Dein, Carol'; Node := Xml.Root.AddChild('book'); Child := Node.AddChild('author'); Child.Text := 'Barger, Al'; Child.Attribute['type'] := 'topseller'; Node.AddChild('title').SetAttribute('lang', 'en').SetText('A big View'); Xml.SaveToFile('output.xml'); Xml.Free; end;
VerySimpleXML supports just a subset of the XML specification
- load and save from stream or file
- nodes, childs and attributes
- UTF-8 and ANSI encoding
- compact output by setting Xml.Ident := ”;
- method chaining
“>” and “>” inside text and attribute values when wrapped in quotation marks (XML-spec requires you to transform them into < etc.)now automatically escaped with v1.1
It does NOT support:
- CDATA, comments, etc…
Example XML-file:
<?xml version="1.0" encoding="utf-8" ?> <catalog> <book id="bk101"> <author>Gambardella, Matthew</author> <title/> <keywords /> </book> <book id=bk102 lang="en"> <author>Ralls, Kim</author> <title>Midnight Rain</title> <description>A former architect battles corporate zombies</description> <keywords> <keyword lang="es">no-muerto</keyword> <keyword lang=en>zombies</keyword> </keywords> </book> <book id="bk103"> <author rate=">5">Corets, Eva</author> <title>Maeve Ascendant</title> <description>The collapse of a <nanotechnology> society</description> </book> </catalog>
Warning! This is not a standard well-formed XML file (not all attributes are wrapped with quotation marks, < and > are used within attributes and text), it is an example of the (very simple) fault tolerance of VerySimpleXML. Version 1.1 automatically escapes all non allowed chars.
22 Comments to VerySimpleXML – a lightweight Delphi XML reader and writer
Nice little unit!
I made an adaptation to let it work in FreePascal
It’s working right now with FreePascal 2.6.0rc1 which introduced generics syntax compatibility with Delphi, still I need to adapt unicode strings to work with FreePascal style unicode strings, but for now it’s working nicely
November 10, 2011
Very nice indeed, thank you very much!
Is the example a valid XML? IE won’t display, FF shows many errors. After fixing question mark in xml tag and some quotes attributes errors, the feature of storing (node) text wrapped in quotation marks is still complained by FF. Am I missing something? Thanks
November 11, 2011
@Broto:
the question mark in the xml tag was just a typo in the example (fixed).
XML-Spec for “well-formed” files requires the attributes wrapped in quotation marks.
VerySimpleXML parses well even without them (if they consist of a single word).
The other non-XML-standard behavior of VerySimpleXML is the usage of the < and > tags inside an attribute or text:
XML spec requires you to write < and > but VerySimpleXML parses well if wrapped in quotation marks.
The XML example just shows these additional VerySimpleXML features. If you feed it with standard well-formed XML files, they will be parsed as well, of course
November 11, 2011
I has the same issues but was able to fix via validation, i have started using a new xml editor I found recently, http://www.liquid-technologies.com/xml-editor.aspx, anyone know where I can get this for free?
Nice API. Not sure if supporting invalid XML is good idea but at some point it may be useful so thanks for this *subset*-XML and *very subset*-SGML parser
November 18, 2011
So nice ! I’ll give it a try. I’ve used Delphi native XML, OmniXML, NativeXML to handle gpx file. Lightweight is appealing.
January 20, 2012
I wonder whether your code can provide me a means of achieving XML of the form:
…
I have battled with TXMLDocument, with no success. All the examples I have seen will get me something of this form:
…
But that is unacceptable.
Thanks for your assistance!
January 20, 2012
I wonder whether your code can provide me a means of achieving XML of the form:
”
…
”
I have battled with TXMLDocument, with no success. All the examples I have seen will get me something of this form:
”
…”
But that is unacceptable.
Thanks for your assistance!
January 20, 2012
My apologies. Apparently I cannot insert XML text in the comment.
January 21, 2012
try using [] instead of &glt;
Hi,
I cannot get this code to compile into delphi 7 – do you have a version that will work in 7?
January 27, 2012
@Philip:
It uses generics, but it should not be that difficult to rewrite those parts without generics (you need to manually free the list objects).
January 29, 2012
[...] VerySimpleXML - очень и очень простой парсер. С ним, собственно, я и начал работать сначала из-за его простоты. [...]
March 23, 2012
Hi, Very nice and elegant code.
I wonder if you can add an alternative to FindNodes that takes an Anonymous method as parameter, so that you can loop the nodes without having to create and free a temporary TXmlNodeList.
Something like:
TXmlNodeCallBack = reference to procedure(node : TXmlNode);
procedure TXmlNode.ScanNodes(Name: String; CallBack : TXmlNodeCallBack);
var
Node: TXmlNode;
begin
Name := lowercase(Name);
for Node in ChildNodes do
if (lowercase(Node.NodeName) = Name) then
CallBack(Node);
end;
Thanks for this great code.
It seems you have a small bug when the file has
and you want to write it back
check it out – I can submit you with example if need be
regards
PW
Given that it is private
FAttributes: TXmlAttributeList;
I would be nice to have methods to able to enumerate attributes captions and values for a node
You can set and get only as long as you know their names
which you might not know ……
Thank you
best
April 20, 2012
You should know all possible attributes of a node – I can’t imagine an example where you’d need a “dynamic unknown” attribute collection?
Something like that would be acceptable??
property AttibuteCount:integer read GetAttibuteCount;
function ListAttributeNames(Items: Tstrings): Integer;
function ListAttributeValues(Items: Tstrings): Integer;
function TXmlNode.GetAttibuteCount: integer;
begin
if not assigned(FAttributes) then
Exit(0);
Result := FAttributes.Count;
end;
function TXmlNode.ListAttributeNames(Items: Tstrings): Integer;
var
Attribute: TXmlAttribute;
begin
Items.Clear;
if not assigned(FAttributes) then
Exit(0);
for Attribute in Self.FAttributes do
Items.Add(Attribute.Name);
Result := FAttributes.Count;
end;
function TXmlNode.ListAttributeValues(Items: Tstrings): Integer;
var
Attribute: TXmlAttribute;
begin
Items.Clear;
if not assigned(FAttributes) then
Exit(0);
for Attribute in Self.FAttributes do
Items.Add(Attribute.Value);
Result := FAttributes.Count;
end;
Sorry it should on on a nodelist not a node
How do you please delete a node
I find it and then I free it but then it cannot save to file
aNode := x.NodeExist(‘flavors’);
if (aNode nil) then
aNode := aNode.Find(‘ROW’, ‘caption’, ‘World’);
if (aNode nil) then
aNode.Free;
then xml.savetofile crashes
any ideas thanks
May 10, 2012
...
if (aNode <> nil) then
begin
// remove node from parent childnodes
if (assigned(aNode.Parent)) then
aNode.Parent.Childnodes.Remove(aNode)
end;
If you remove a node, all you have to do is to remove it from the parent childnodes and the node will be freed by the removal procedure.
As only the root node has no parent, you may even omit the “assigned check”, as a “find” call won’t return the root node itself:
...
if (aNode <> nil) then
// remove node from parent childnodes, the node itself will be freed then
aNode.Parent.Childnodes.Remove(aNode);
Leave a comment
About
Recent Posts
- VerySimpleXML – a lightweight Delphi XML reader and writer
- Solving circular unit references with class helpers
- How to change the language of the Cisco SPA504G
- Eclipse on Mac OS X – Workspace error on NFS mounts
- Lua 5.1 for Delphi 2010
- WordPress Plugin – QR Code Tag v1.0
- Favourite Android applications
- Hint: Blank Typo3 installation screen
- How to create an ESXi v4 Whitebox ISO with Windows Tools
- Ext: tt_news – no translation for name of months
Search
Categories
Tags
Archives
Delphi Feeds
- OmniThreadLibrary Documentation: ParallelTask
- You can’t remove open-source code from public use
- Laying out Smart applications with Layout Manager [3]
- HotFix 1 is live!
- From OP4JS to Smart Mobile Studio
- Update 4 Hotfix 1 now available for Delphi, C++Builder and RAD Studio XE2
- Charles Petzold Rides Again (+ praise for Kindle and O’Reilly)
- Delphi Language links/info
- Limit The Number Of Characters For The TListView's Editor Control
- Embarcadero Academy–The Multithreading Session
I'm an avid programmer working on a variety of platforms in a variety of languages with a wide technical interest.


November 10, 2011