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();
    }
}
Last modified 8 years ago Last modified on Feb 14, 2009, 12:09:43 PM