XmlElement derived class


#1

This is probably a c++ question more than a juce question but here goes.

How can I create a derived class from XmlElement that has a few more functions?

For example:

void CXmlElement::setAttribute (const String &attributeName, int *pInts, int numInts);

void CXmlElement::getAttribute (const String &attributeName, int *pInts, int numInts);

CXmlElement *CXmlElement::createNewChildElement(const String &attributeName);

CXmlElement *CXmlElement::getChildByName(StringRef tagNameToLookFor);

CXmlElement *CXmlElement::getChildElement(int index);

The problems are:

1) How to create a child CXmlElement. Can you down cast/up cast createChildElement/getChildByName etc.

2) To read in the element I am using XmlDocument::parse. So again is there a down cast/up cast solution.

I hope this is clear. Any solutions are welocme. I could add these directly to the juce code, bu prefer not to.


#2

NOOOOO!!!! Such bad c++ style, I feel pain even reading it!

Just write stand-alone functions that take the XmlElement& parameter and modify or read it. It's a perfect example of a situation where inheritance is absolutely the wrong thing to use!


#3

"take the XmlElement& parameter and modify or read it". 

That is what I am currently doing, but was hoping for another cool method because I am starting to add a few more routines. I researched it but couldn't find a clean safe method, so I asked the C++ gurus here on the forum.

Adding the array of ints might be good for users, as well as a few more routines like setAttribute for Rect and Point. This avoids having to convert back and forth to strings. BTW, Point has a toString but not a fromString. Rect has both of them.

One more note. My Xml files are very large (8-12 Mb) and when I read a large file into MemoryBlock and try to convert it to a XmlElement it crashes. If I take the same file and ::parse it, no problem. Just thought I would mention it.

Thank you for all the routines. I am storing my file format as a compressed XmlElement and it sure makes it nice for debugging. And I think I am going to add BlowFish.


#4

It's definitely best for the XmlElement class to know nothing about more complex types than the primitive ones it handles. There are hundreds of different ways that people might choose to encode an int array, Rectangle, or Point as XML, so for the core class itself to supply methods to do that would be bad form. That's why the correct thing that any self-respecting guru would recommend is for you to write your own stand-alone functions to encode them however it's appropriate for your app!

12Mb isn't big, BTW, and all that the ::parse method does is to load the file into memory and parse it, so if you've got a crash, it's probably because of something you're doing to mess-up the memory before passing it to the parser.


#5

10Mb is large when you try to read it in a browser.

All I was doing is reading the file into a MemoryBlock, converting it to a string and then into the XmlElement. You had suggested this somewhere else on the forum. Anyway what I am doing now is working. Also I am having another related problem and I read this on the forum that others were also. When I use a temporary file that writes as a GZIPCompressorOutputStream, I can't delete the temporary file afterwards.

void save( const File &juceFile, const XmlElement &element )
{
    File tempFile = File (juceFile.withFileExtension("tempx")); 

    //Write temp file as a compressed zip file
    FileOutputStream    outputStream ( tempFile );
    GZIPCompressorOutputStream zipOutStream (&outputStream, 9);
    
    element.writeToStream (zipOutStream, "");
    zipOutStream.flush();
    
    //Now rename it to
    bool bResult = tempFile.copyFileTo (juceFile.withFileExtension ("ovex"));
    bResult = tempFile.deleteFile();
}

The tempFile.deleteFile() returns false and the file is still on the drive. In my code I am using File::createTempFile so the user will not see it if something goes wrong. I assume the File::createTempFile is being left on the hard drive because of this.

Any ideas?


#6

You're trying to copy/delete the file before you've even closed the stream that's writing to it!

And there's a TemporaryFile class to do exactly this stuff for you automatically.