3
XeromycesExample
Ykkrosh edited this page 2009-02-14 12:09:43 +01:00
Consider a hypothetical XML-based image format:
<?xml version="1.0" encoding="utf-8"?>
<image>
<width>2</width>
<height>2</height>
<row>
<pixel red="255" green="0" blue="255"/>
<pixel red="255" green="0" blue="128"/>
</row>
<row>
<pixel red="255" green="0" blue="128"/>
<pixel red="255" green="0" blue="0"/>
</row>
</image>
The code to read it would look something like:
#include "ps/XML/Xeromyces.h"
void ReadImage(const char* Filename)
{
// First you need to load an XML file from disk. It uses the VFS system,
// so put all the XML files inside data/mods/official/<Filename>.
// The XML is automatically converted to an XMB when necessary.
// Load() returns either PSRETURN_OK or a PSRETURN_Xeromyces_*
CXeromyces XeroFile;
if (XeroFile.Load(Filename) != PSRETURN_OK)
// Loading failed - respond in whatever way is appropriate.
return;
// Rather than doing a large number of string comparisons, Xeromyces
// gives a unique numeric ID to each element and attribute name in a
// file; the numbers must therefore be read before you can understand
// the file's content.
//
// The element/attribute names *must* be specified here in lowercase.
// (The system is case-sensitive; the XML files are automatically
// converted to lowercase, but strings in the code aren't.)
//
// If an element/attribute doesn't exist in that particular file,
// it will return an ID of -1.
int el_image = XeroFile.getElementID("image");
int el_width = XeroFile.getElementID("width");
int el_height = XeroFile.getElementID("height");
int el_row = XeroFile.getElementID("row");
// All XML files have a single root element (in this example it's
// the <image>). The "XMBElement" class provides access to the
// element.
XMBElement Root = XeroFile.getRoot();
// If you're paranoid, check that you're actually reading the
// correct type of XML file.
assert(Root.getNodeName() == el_image);
// Some uninteresting things to help with the example:
int width, height;
pixel pixels[MAX_IMAGE_SIZE][MAX_IMAGE_SIZE];
int y = 0;
// You now iterate through each child element of the root element -
// in this example, the children are <width>, <height> and two <row>s.
XMBElementList RootChildren = Root.getChildNodes();
for (int i = 0; i < RootChildren.Count; ++i)
{
XMBElement Child = RootChildren.item(i);
// Now you check what type of element it is, and respond appropriately.
int ChildName = Child.getNodeName();
if (ChildName == el_width)
{
CStr val (Child.getText());
width = val.ToInt();
}
// It's possible to use strings rather than the IDs, although
// it isn't particularly efficient.
// getElementString translates an ID back into a string.
else if (XeroFile.getElementString(ChildName) == "height")
{
CStr val (Child.getText());
height = val.ToInt();
}
else if (ChildName == el_row)
{
// Since XML files tend to be recursive, it's generally nicer
// to split things into several functions.
ReadPixelRow(Child, XeroFile, pixels[y++]);
}
}
}
// XMBElements are only 4 bytes, so there's no need to pass them
// around in a more efficient way.
void ReadPixelRow(XMBElement Row, CXeromyces& XeroFile, pixel* Pixels)
{
// Load the IDs for the elements/attributes that are
// going to be used in this pixel.
int el_pixel = XeroFile.getElementID("pixel");
int at_red = XeroFile.getAttributeID("red");
int at_green = XeroFile.getAttributeID("green");
int at_blue = XeroFile.getAttributeID("blue");
// Iterate through the children again
XMBElementList Children = Row.getChildNodes();
for (int x = 0; x < Children.Count; ++x)
{
XMBElement Pixel = Children.item(x);
assert(Pixel.getNodeName() == el_pixel);
// You can iterate through the attributes in the same way:
XMBAttributeList Attrs = Pixel.getAttributes();
for (int i = 0; i < Attrs.Count; ++i)
{
XMBAttribute Attr = Attrs.item(i);
if (Attr.Name == at_red)
{
CStr val (Attr.Value);
Pixels[x].r = val.ToInt();
}
else if (Attr.Name == at_green)
{
CStr val (Attr.Value);
Pixels[x].g = val.ToInt();
}
}
// You can also get attributes by asking for a particular
// one, which is sometimes more convenient.
// getNamedItem() returns an empty string if the attribute
// has not been specified in the file.
CStr val (Attrs.getNamedItem(at_blue));
Pixels[x].b = val.ToInt();
}
}