(http://apps.soldat2d.com/projects/libxml/logo/48x48.png)
libxml
Download (#post_Download)
The libxml library provides set of functions to easily add XML parsing and creating capability to SoldatServer scripts. It is based on the Expat XML parser (http://expat.sourceforge.net/), which is licensed under the MIT license which can be viewed in the post footer. Expat is used in many projects (like Mozilla or Perl). It is very stable and very fast.
Important: The Expat license requires that a copyright notice and the license text itself be included in any software that includes the parser. So if this library is used in software that is to be made public, the license below (#post_Expat_Lisence) must be included with the software.
This library has partial support for Document Type Definitions (DTD) and Namespaces. The goal is to keep the commandset very simple while still allowing this library to handle any XML compliant document.
The official specification of XML and XML Namespaces by the W3C can be found here:
XML specification (http://www.w3.org/TR/REC-xml/)
XML Namespaces (http://www.w3.org/TR/REC-xml-names/)
Various translations of XML related documents (http://www.w3.org/XML/Core/Translations)
Also the Wikipedia article on XML (http://en.wikipedia.org/wiki/Xml) provides a good starting point for people new to XML.
// =====================================
// U S A G E
// =====================================
- Extract an attached archive into the root of your SoldatServer directory.
Thus libxml.dll (Windows) and libxml.so (Linux) will be placed near to soldatserver.exe (Windows) and soldatserver (Linux) executable files and /libxml directory with an examples code will be copied into the /scripts directory of your server. - Run server using a "-safe 0" command line switch.
// =====================================
// N O T E S
// =====================================
Windows:
- Everything should work out of the box
Linux:
- You should comment the "libxml_windows.pas" line and uncomment the "libxml_linux.pas" line in the /libxml/Includes.txt file to make an example code work on Linux.
- There could be a need to do an export of LD_LIBRARY_PATH (export LD_LIBRARY_PATH=/path/to/soldatserver) to use external library functions
// =====================================
// E X A M P L E S
// =====================================
// =====================================
// C O N S T A N T S
// =====================================
Const
XML_Any = -1;
XML_All = -1;
XML_Ascii = 24;
XML_Unicode = 25;
XML_UTF8 = 2;
XML_Root = 0;
XML_Normal = 1;
XML_Comment = 2;
XML_CData = 3;
XML_DTD = 4;
XML_Instruction = 5;
XML_WindowsNewline = 1; // Changes all newline to CRLF
XML_LinuxNewline = 2; // Changes all newline to LF
XML_MacNewline = 4; // Changes all newline to CR
XML_CutNewline = 8; // Removes all newline
XML_ReduceNewline = 16; // Removes all empty lines
XML_CutSpace = 32; // Removes all spaces
XML_ReduceSpace = 64; // Removes all multiple spaces
XML_ReFormat = 128; // Completely reformats the tree structure
XML_ReIndent = 256; // Changes the indentation of the lines
XML_StandaloneYes = 1; // The document mode is standalone
XML_StandaloneNo = 0; // The document mode is not standalone
XML_StandaloneUnset = -1; // The standalone mode is not specified in the declaration
XML_StringFormat = 1; // Includes a byte order mark (BOM)
XML_NoDeclaration = 2; // Does not include the XML declaration
XML_Success = 0; // no error
XML_NoMemory = 1; // out of memory
XML_Syntax = 2; // syntax error
XML_NoElements = 3; // no element found
XML_InvalidToken = 4; // not well-formed (invalid token)
XML_UnclosedToken = 5; // unclosed token
XML_PartialCharacter = 6; // partial character
XML_TagMismatch = 7; // mismatched tag
XML_DublicateAttribute = 8; // duplicate attribute
XML_JunkAfterDocElement = 9; // junk after document element
XML_ParamEntityRef = 10; // illegal parameter entity reference
XML_UndefinedEntity = 11; // undefined entity
XML_RecursiveEntityRef = 12; // recursive entity reference
XML_AsyncEntity = 13; // asynchronous entity
XML_BadCharacterRef = 14; // reference to invalid character number
XML_BinaryEntityRef = 15; // reference to binary entity
XML_AttributeExternalEntityRef = 16; // reference to external entity in attribute
XML_MisplacedXML = 17; // XML or text declaration not at start of entity
XML_UnknownEncoding = 18; // unknown encoding
XML_IncorrectEncoding = 19; // encoding specified in XML declaration is incorrect
XML_UnclosedCDataSection = 20; // unclosed CDATA section
XML_ExternalEntityHandling = 21; // error in processing external entity reference
XML_NotStandalone = 22; // document is not standalone
XML_UnexpectedState = 23; // unexpected parser state
XML_EntityDeclaredInPE = 24; // entity declared in parameter entity
XML_FeatureRequiresDTD = 25; // requested feature requires XML_DTD support in Expat
XML_CantChangeFeatures = 26; // cannot change setting once parsing has begun
XML_UnboundPrefix = 27; // unbound prefix
XML_UndeclaringPrefix = 28; // must not undeclare prefix
XML_IncompletePE = 29; // incomplete markup in parameter entity
XML_XMLDeclaration = 30; // XML declaration not well-formed
XML_TextDeclaration = 31; // text declaration not well-formed
XML_PublicID = 32; // illegal character(s) in public id
XML_Suspended = 33; // parser suspended
XML_NotSuspended = 34; // parser not suspended
XML_Aborted = 35; // parsing aborted
XML_Finished = 36; // parsing finished
XML_SuspendedPE = 37; // cannot suspend in external parameter entity
XML_ReservedPrefixXML = 38; // reserved prefix (xml) must not be undeclared or bound to another namespace name
XML_ReservedPrefixXMLNS = 39; // reserved prefix (xmlns) must not be declared or undeclared
XML_ReservedNamespaceURI = 40; // prefix must not be bound to one of the reserved namespace names
// =====================================
// D E C L A R A T I O N S
// =====================================
//Function XML_ChildNode(Node: Integer; Index: Integer = -1): Integer;
Function XML_ChildNode(Node, Index: Integer): Integer;
External 'XML_ChildNode@libxml.dll cdecl';
//Function XML_CopyNode(Node, ParentNode: Integer; PreviousNode: Integer = 0): Integer;
Function XML_CopyNode(Node, ParentNode, PreviousNode: Integer): Integer;
External 'XML_CopyNode@libxml.dll cdecl';
//Function XML_Create(XML: Integer; Encoding: Integer = XML_UTF8): Integer;
Function XML_Create(XML, Encoding: Integer): Integer;
External 'XML_Create@libxml.dll cdecl';
//Function XML_CreateNode(ParentNode: Integer; PreviousNode: Integer = 0; TType: Integer = XML_Normal): Integer;
Function XML_CreateNode(ParentNode, PreviousNode, TType: Integer): Integer;
External 'XML_CreateNode@libxml.dll cdecl';
Procedure XML_DeleteNode(Node: Integer);
External 'XML_DeleteNode@libxml.dll cdecl';
Function XML_ExamineAttributes(Node: Integer): Integer;
External 'XML_ExamineAttributes@libxml.dll cdecl';
//Procedure XML_Format(XML, Flags: Integer; IndentStep: Integer = -1);
Procedure XML_Format(XML, Flags, IndentStep: Integer);
External 'XML_Format@libxml.dll cdecl';
Procedure XML_Free(XML: Integer);
External 'XML_Free@libxml.dll cdecl';
Function XML_GetAttribute(Node: Integer; Attribute: PChar): PChar;
External 'XML_GetAttribute@libxml.dll cdecl';
Function XML_GetEncoding(XML: Integer): Integer;
External 'XML_GetEncoding@libxml.dll cdecl';
Function XML_GetNodeName(Node: Integer): PChar;
External 'XML_GetNodeName@libxml.dll cdecl';
Function XML_GetNodeOffset(Node: Integer): Integer;
External 'XML_GetNodeOffset@libxml.dll cdecl';
Function XML_GetNodeText(Node: Integer): PChar;
External 'XML_GetNodeText@libxml.dll cdecl';
Function XML_GetStandalone(XML: Integer): Integer;
External 'XML_GetStandalone@libxml.dll cdecl';
Function XML_IsXML(XML: Integer): Integer;
External 'XML_IsXML@libxml.dll cdecl';
//Function XML_Load(XML: Integer; Filename: PChar; Encoding: Integer = -1): Integer;
Function XML_Load(XML: Integer; Filename: PChar; Encoding: Integer): Integer;
External 'XML_Load@libxml.dll cdecl';
Function XML_MainNode(XML: Integer): Integer;
External 'XML_MainNode@libxml.dll cdecl';
//Function XML_MoveNode(Node, ParentNode: Integer; PreviousNode: Integer = -1): Integer;
Function XML_MoveNode(Node, ParentNode, PreviousNode: Integer): Integer;
External 'XML_MoveNode@libxml.dll cdecl';
Function XML_NextAttribute(Node: Integer): Integer;
External 'XML_NextAttribute@libxml.dll cdecl';
Function XML_NextNode(Node: Integer): Integer;
External 'XML_NextNode@libxml.dll cdecl';
Function XML_ParentNode(Node: Integer): Integer;
External 'XML_ParentNode@libxml.dll cdecl';
Function XML_PreviousNode(Node: Integer): Integer;
External 'XML_PreviousNode@libxml.dll cdecl';
Procedure XML_RemoveAttribute(Node: Integer; Attribute: PChar);
External 'XML_RemoveAttribute@libxml.dll cdecl';
//Function XML_ResolveAttributeName(Node: Integer; Attribute: PChar; Separator: PChar = '/'): PChar;
Function XML_ResolveAttributeName(Node: Integer; Attribute, Separator: PChar): PChar;
External 'XML_ResolveAttributeName@libxml.dll cdecl';
//Function XML_ResolveNodeName(Node: Integer; Separator: PChar = '/'): PChar;
Function XML_ResolveNodeName(Node: Integer; Separator: PChar): PChar;
External 'XML_ResolveNodeName@libxml.dll cdecl';
Function XML_RootNode(XML: Integer): Integer;
External 'XML_RootNode@libxml.dll cdecl';
//Function XML_Save(XML: Integer; Filename: PChar; Flags: Integer = -1): Integer;
Function XML_Save(XML: Integer; Filename: PChar; Flags: Integer): Integer;
External 'XML_Save@libxml.dll cdecl';
Procedure XML_SetAttribute(Node: Integer; Attribute, Value: PChar);
External 'XML_SetAttribute@libxml.dll cdecl';
Procedure XML_SetEncoding(XML, Encoding: Integer);
External 'XML_SetEncoding@libxml.dll cdecl';
Procedure XML_SetNodeName(Node: Integer; Name: PChar);
External 'XML_SetNodeName@libxml.dll cdecl';
Procedure XML_SetNodeOffset(Node, Offset: Integer);
External 'XML_SetNodeOffset@libxml.dll cdecl';
Procedure XML_SetNodeText(Node: Integer; Text: PChar);
External 'XML_SetNodeText@libxml.dll cdecl';
Procedure XML_SetStandalone(XML, Standalone: Integer);
External 'XML_SetStandalone@libxml.dll cdecl';
Function XML_AttributeName(Node: Integer): PChar;
External 'XML_AttributeName@libxml.dll cdecl';
Function XML_AttributeValue(Node: Integer): PChar;
External 'XML_AttributeValue@libxml.dll cdecl';
Function XML_ChildCount(Node: Integer): Integer;
External 'XML_ChildCount@libxml.dll cdecl';
Function XML_Error(XML: Integer): PChar;
External 'XML_Error@libxml.dll cdecl';
Function XML_ErrorLine(XML: Integer): Integer;
External 'XML_ErrorLine@libxml.dll cdecl';
Function XML_ErrorPosition(XML: Integer): Integer;
External 'XML_ErrorPosition@libxml.dll cdecl';
Function XML_NodeFromID(XML: Integer; ID: PChar): Integer;
External 'XML_NodeFromID@libxml.dll cdecl';
Function XML_NodeFromPath(ParentNode: Integer; Path: PChar): Integer;
External 'XML_NodeFromPath@libxml.dll cdecl';
//Function XML_NodePath(Node: Integer; ParentNode: Integer = -1): PChar;
Function XML_NodePath(Node, ParentNode: Integer): PChar;
External 'XML_NodePath@libxml.dll cdecl';
Function XML_NodeType(Node: Integer): Integer;
External 'XML_NodeType@libxml.dll cdecl';
Function XML_Status(XML: Integer): Integer;
External 'XML_Status@libxml.dll cdecl';
Function XML_GetVersion(): Integer;
External 'XML_GetVersion@libxml.dll cdecl';
// =====================================
// E X A M P L E S
// =====================================
procedure test_save();
var
FileName: String;
XML, MainNode, Item, SubItem: Integer;
begin
FileName := 'weapons.xml';
// Create xml tree
XML := XML_Create(XML_Any, XML_Ascii);
MainNode := XML_CreateNode(XML_RootNode(XML), -1, XML_Normal);
XML_SetNodeName(MainNode, 'Weapons');
// Create first xml node (in main node)
Item := XML_CreateNode(MainNode, -1, XML_Normal);
XML_SetNodeName(Item, 'Weapon');
XML_SetAttribute(Item, 'ID', '1');
XML_SetAttribute(Item, 'ShortName', 'DE');
XML_SetNodeText(Item, 'Desert Eagles');
// Create a child node (in first node)
SubItem := XML_CreateNode(Item, 0, XML_Normal);
XML_SetNodeName(SubItem, 'Properties');
XML_SetAttribute(SubItem, 'Damage', '186');
XML_SetAttribute(SubItem, 'Ammo', '7');
// Create second xml node (in main node)
Item := XML_CreateNode(MainNode, -1, XML_Normal);
XML_SetNodeName(Item, 'Weapon');
XML_SetAttribute(Item, 'ID', '2');
XML_SetAttribute(Item, 'ShortName', 'MP5');
XML_SetNodeText(Item, 'HK MP5');
// Create a child node (in second node)
SubItem := XML_CreateNode(Item, 0, XML_Normal);
XML_SetNodeName(SubItem, 'Properties');
XML_SetAttribute(SubItem, 'Damage', '104');
XML_SetAttribute(SubItem, 'Ammo', '30');
// Save the xml tree into a xml file
XML_Format(XML, XML_ReFormat, 2);
if XML_Save(XML, FileName, XML_StringFormat) <> 0 then
WriteLn('File "' + FileName + '" has been saved...')
else
WriteLn('Can not save "' + FileName + '" file...');
XML_Free(XML);
end;
// This procedure prints all childnodes by recursively calling itself
procedure PrintNodes(CurrentNode, CurrentSublevel: Integer);
var
Text: String;
ChildNode: Integer;
begin
// Ignore anything except normal nodes. See the manual for
// XML_NodeType() for an explanation of the other node types
if XML_NodeType(CurrentNode) = XML_Normal then begin
// Print this node. Add name and attributes
Text := '';
while Length(Text) < CurrentSublevel do
Text := Text + '+';
Text := Text + XML_GetNodeName(CurrentNode) + ' ( Attributes: ';
if XML_ExamineAttributes(CurrentNode) <> 0 then
while XML_NextAttribute(CurrentNode) <> 0 do
Text := Text + XML_AttributeName(CurrentNode) + '=' + #34 + XML_AttributeValue(CurrentNode) + #34 + ' ';
Text := Text + ')';
WriteLn(Text);
// Now get the first child node (if any)
ChildNode := XML_ChildNode(CurrentNode, 1);
// Loop through all available child nodes and call this procedure again
while ChildNode <> 0 do begin
PrintNodes(ChildNode, CurrentSublevel + 1);
ChildNode := XML_NextNode(ChildNode);
end;
end;
end;
procedure test_load();
var
FileName: String;
XML, MainNode: Integer;
begin
FileName := 'weapons.xml';
XML := XML_Load(XML_Any, FileName, XML_Any);
if XML <> 0 then begin
{ Note:
The XML_Load() succeed if the file could be read. This does not mean that
there was no error in the XML though. To check this, XML_Status() can be
used.
}
// Display an error message if there was a markup error
if XML_Status(XML) <> XML_Success then begin
WriteLn('Error in the XML file:');
WriteLn('Message: ' + XML_Error(XML));
WriteLn('Line: ' + IntToStr(XML_ErrorLine(XML)) + '; Character: ' + IntToStr(XML_ErrorPosition(XML)));
end;
{ Note:
Even if there was an error in the XML, all nodes before the error position
are still accessible, so open the window and show the tree anyway.
}
// Get the main XML node and call the PrintNodes() procedure with it
MainNode := XML_MainNode(XML);
if MainNode <> 0 then
PrintNodes(MainNode, 0);
XML_Free(XML);
end
else
WriteLn('Can not load "' + FileName + '" file...');
end;
procedure OnAdminMessage(IP, Msg: String);
begin
case LowerCase(Trim(Msg)) of
'/save' : test_save();
'/load' : test_load();
'/ver' : WriteLn('libxml v0.'+IntToStr(XML_GetVersion()));
end;
end;
// =====================================
License for the Expat XML parser
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
and Clark Cooper
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
P.S. The icon was based on the art made by New Mooon (http://code.google.com/u/newmooon/).
P.P.S. Unicode version of the library (Windows & Linux) attached in case you would like to use it in some of your apps or SoldatServer will someday become a fully Unicode compatible.