PropertySet XML value formatting


#1

I’m using the excellent PropertySet class, and just added an XML value to it, but I see that when written to a file, it comes out quite mangled. Of course, it reads itself well, but it misses the best feature of both that class (as XML) and of XML itself - the human readable and editable aspect.

Is that something that could be altered? Currently I get:

But of course I’d rather get something like:

<VALUE name="currentOutputs"> <OUTPUT ID="0" Name="GUI" type="Video"> <MODE Value="GUI"/> <SIGNAL Value="Window"/> <STANDARD Value="NTSC"/> <CARD Value="1"/> <CONNECTOR Value="1"/> <GENLOCK Value="Int"/> <WIDTH Value="800"/> <HEIGHT Value="600"/> <ASPECT Value="1.333"/> <INTERLACE Value="Prog"/> <COLORSPACE Value="Auto"/> <COLOR_DEPTH Value="8-bit"/> <COLOR_CODING Value="Auto"/> </OUTPUT> </VALUE>

Note that an XML editor also can’t open the current version. It doesn’t seem like much would be broken by this, since the PropertySet only looks for tags in the root element anyway.

Bruce


#2

Yes, it does that because it stores all its values as strings. I think I’ve already got this on my to-do-list somewhere.


#3

Well, I’ll probably do it here then and then change to your version when you have it.

Any suggestion on how to get to the structure I defined? Is it acceptable to pass the XML elements in a donor XmlElement, or do you think the VALUE element will have to hold the incoming element:

Preferable but involves a donor: <VALUE name="currentOutputs"> <OUTPUT ID="0" Name="GUI" type="Video"> <ASPECT Value="1.333"/> <INTERLACE Value="Prog"/> <COLORSPACE Value="Auto"/> <COLOR_DEPTH Value="8-bit"/> <COLOR_CODING Value="Auto"/> </OUTPUT> </VALUE>

More understandable to set but harder to get/parse: <VALUE name="currentOutputs"> <OUTPUTS> <OUTPUT ID="0" Name="GUI" type="Video"> <ASPECT Value="1.333"/> <INTERLACE Value="Prog"/> <COLORSPACE Value="Auto"/> <COLOR_DEPTH Value="8-bit"/> <COLOR_CODING Value="Auto"/> </OUTPUT> </OUTPUTS> </VALUE>

Bruce


#4

I’d have thought it would just set/get a single xml node, which would go inside the value node. It’s up to your app what the structure of that node would be.


#5

I thought you’d say that. So my case B. I’ll post back when I have something.

Bruce


#6

OK, so after putting changes in PropertySet CreateXML and then scratching head a lot, this seems to work:

[code]bool PropertiesFile::save()
{
const ScopedLock sl (getLock());

stopTimer();

if (file == File::nonexistent
     || file.isDirectory()
     || ! file.getParentDirectory().createDirectory())
    return false;

if ((options & storeAsXML) != 0)
{
    XmlElement* const doc = new XmlElement (propertyFileXmlTag);

    for (int i = 0; i < getAllProperties().size(); ++i)
    {
        XmlElement* const e = new XmlElement (propertyTagName);
        e->setAttribute (T("name"), getAllProperties().getAllKeys() [i]);
		
		// Can the value be best expressed as XML?
		XmlDocument xmlVal (getAllProperties().getAllValues()[i]);
		if (xmlVal.getDocumentElement(true))
		{
			e->addChildElement(new XmlElement(*xmlVal.getDocumentElement()));
		}
		else
			e->setAttribute (T("val"), getAllProperties().getAllValues() [i]);
		
        doc->addChildElement (e);
    }

    const bool ok = doc->writeToFile (file, String::empty);

[/code]

and in the constructor…[code] if (doc != 0 && doc->hasTagName (propertyFileXmlTag))
{
delete doc;
doc = parser.getDocumentElement();

            if (doc != 0)
            {
                forEachXmlChildElementWithTagName (*doc, e, propertyTagName)
                {
                    const String name (e->getStringAttribute (T("name")));
					
                    if (name.isNotEmpty())
					{
						if (e->hasAttribute (T("val")))
						{
							getAllProperties().set (name, e->getStringAttribute (T("val")));
						}
						else if (e->getNumChildElements() == 1)
						{
							getAllProperties().set (name, e->getChildElement(0)->createDocument (String::empty, true));
						}
					}
                }
            }
            else
            {
                // must be a pretty broken XML file we're trying to parse here!
                jassertfalse
            }

            delete doc;
        }

[/code]

Bruce


#7

Thanks Bruce, that was along the right lines! I’ve checked in my interpretation now (same thing, minus the memory leaks)!