Consider a hypothetical XML-based image format: {{{ #!xml 2 2 }}} The code to read it would look something like: {{{ #!cpp #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/. // 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 ). 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 , and two 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(); } } }}}