Fix crash when host does not support midi-in; Add missing file
[juce-lv2.git] / juce / source / src / text / juce_XmlElement.h
blob370d94e78baab1c84b1d5f6a508174ac4857ee39
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #ifndef __JUCE_XMLELEMENT_JUCEHEADER__
27 #define __JUCE_XMLELEMENT_JUCEHEADER__
29 #include "juce_String.h"
30 #include "../io/streams/juce_OutputStream.h"
31 #include "../io/files/juce_File.h"
32 #include "../containers/juce_LinkedListPointer.h"
35 //==============================================================================
36 /** A handy macro to make it easy to iterate all the child elements in an XmlElement.
38 The parentXmlElement should be a reference to the parent XML, and the childElementVariableName
39 will be the name of a pointer to each child element.
41 E.g. @code
42 XmlElement* myParentXml = createSomeKindOfXmlDocument();
44 forEachXmlChildElement (*myParentXml, child)
46 if (child->hasTagName ("FOO"))
47 doSomethingWithXmlElement (child);
50 @endcode
52 @see forEachXmlChildElementWithTagName
54 #define forEachXmlChildElement(parentXmlElement, childElementVariableName) \
56 for (JUCE_NAMESPACE::XmlElement* childElementVariableName = (parentXmlElement).getFirstChildElement(); \
57 childElementVariableName != 0; \
58 childElementVariableName = childElementVariableName->getNextElement())
60 /** A macro that makes it easy to iterate all the child elements of an XmlElement
61 which have a specified tag.
63 This does the same job as the forEachXmlChildElement macro, but only for those
64 elements that have a particular tag name.
66 The parentXmlElement should be a reference to the parent XML, and the childElementVariableName
67 will be the name of a pointer to each child element. The requiredTagName is the
68 tag name to match.
70 E.g. @code
71 XmlElement* myParentXml = createSomeKindOfXmlDocument();
73 forEachXmlChildElementWithTagName (*myParentXml, child, "MYTAG")
75 // the child object is now guaranteed to be a <MYTAG> element..
76 doSomethingWithMYTAGElement (child);
79 @endcode
81 @see forEachXmlChildElement
83 #define forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \
85 for (JUCE_NAMESPACE::XmlElement* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \
86 childElementVariableName != 0; \
87 childElementVariableName = childElementVariableName->getNextElementWithTagName (requiredTagName))
90 //==============================================================================
91 /** Used to build a tree of elements representing an XML document.
93 An XML document can be parsed into a tree of XmlElements, each of which
94 represents an XML tag structure, and which may itself contain other
95 nested elements.
97 An XmlElement can also be converted back into a text document, and has
98 lots of useful methods for manipulating its attributes and sub-elements,
99 so XmlElements can actually be used as a handy general-purpose data
100 structure.
102 Here's an example of parsing some elements: @code
103 // check we're looking at the right kind of document..
104 if (myElement->hasTagName ("ANIMALS"))
106 // now we'll iterate its sub-elements looking for 'giraffe' elements..
107 forEachXmlChildElement (*myElement, e)
109 if (e->hasTagName ("GIRAFFE"))
111 // found a giraffe, so use some of its attributes..
113 String giraffeName = e->getStringAttribute ("name");
114 int giraffeAge = e->getIntAttribute ("age");
115 bool isFriendly = e->getBoolAttribute ("friendly");
119 @endcode
121 And here's an example of how to create an XML document from scratch: @code
122 // create an outer node called "ANIMALS"
123 XmlElement animalsList ("ANIMALS");
125 for (int i = 0; i < numAnimals; ++i)
127 // create an inner element..
128 XmlElement* giraffe = new XmlElement ("GIRAFFE");
130 giraffe->setAttribute ("name", "nigel");
131 giraffe->setAttribute ("age", 10);
132 giraffe->setAttribute ("friendly", true);
134 // ..and add our new element to the parent node
135 animalsList.addChildElement (giraffe);
138 // now we can turn the whole thing into a text document..
139 String myXmlDoc = animalsList.createDocument (String::empty);
140 @endcode
142 @see XmlDocument
144 class JUCE_API XmlElement
146 public:
147 //==============================================================================
148 /** Creates an XmlElement with this tag name. */
149 explicit XmlElement (const String& tagName) noexcept;
151 /** Creates a (deep) copy of another element. */
152 XmlElement (const XmlElement& other);
154 /** Creates a (deep) copy of another element. */
155 XmlElement& operator= (const XmlElement& other);
157 /** Deleting an XmlElement will also delete all its child elements. */
158 ~XmlElement() noexcept;
160 //==============================================================================
161 /** Compares two XmlElements to see if they contain the same text and attiributes.
163 The elements are only considered equivalent if they contain the same attiributes
164 with the same values, and have the same sub-nodes.
166 @param other the other element to compare to
167 @param ignoreOrderOfAttributes if true, this means that two elements with the
168 same attributes in a different order will be
169 considered the same; if false, the attributes must
170 be in the same order as well
172 bool isEquivalentTo (const XmlElement* other,
173 bool ignoreOrderOfAttributes) const noexcept;
175 //==============================================================================
176 /** Returns an XML text document that represents this element.
178 The string returned can be parsed to recreate the same XmlElement that
179 was used to create it.
181 @param dtdToUse the DTD to add to the document
182 @param allOnOneLine if true, this means that the document will not contain any
183 linefeeds, so it'll be smaller but not very easy to read.
184 @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the
185 document
186 @param encodingType the character encoding format string to put into the xml
187 header
188 @param lineWrapLength the line length that will be used before items get placed on
189 a new line. This isn't an absolute maximum length, it just
190 determines how lists of attributes get broken up
191 @see writeToStream, writeToFile
193 String createDocument (const String& dtdToUse,
194 bool allOnOneLine = false,
195 bool includeXmlHeader = true,
196 const String& encodingType = "UTF-8",
197 int lineWrapLength = 60) const;
199 /** Writes the document to a stream as UTF-8.
201 @param output the stream to write to
202 @param dtdToUse the DTD to add to the document
203 @param allOnOneLine if true, this means that the document will not contain any
204 linefeeds, so it'll be smaller but not very easy to read.
205 @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the
206 document
207 @param encodingType the character encoding format string to put into the xml
208 header
209 @param lineWrapLength the line length that will be used before items get placed on
210 a new line. This isn't an absolute maximum length, it just
211 determines how lists of attributes get broken up
212 @see writeToFile, createDocument
214 void writeToStream (OutputStream& output,
215 const String& dtdToUse,
216 bool allOnOneLine = false,
217 bool includeXmlHeader = true,
218 const String& encodingType = "UTF-8",
219 int lineWrapLength = 60) const;
221 /** Writes the element to a file as an XML document.
223 To improve safety in case something goes wrong while writing the file, this
224 will actually write the document to a new temporary file in the same
225 directory as the destination file, and if this succeeds, it will rename this
226 new file as the destination file (overwriting any existing file that was there).
228 @param destinationFile the file to write to. If this already exists, it will be
229 overwritten.
230 @param dtdToUse the DTD to add to the document
231 @param encodingType the character encoding format string to put into the xml
232 header
233 @param lineWrapLength the line length that will be used before items get placed on
234 a new line. This isn't an absolute maximum length, it just
235 determines how lists of attributes get broken up
236 @returns true if the file is written successfully; false if something goes wrong
237 in the process
238 @see createDocument
240 bool writeToFile (const File& destinationFile,
241 const String& dtdToUse,
242 const String& encodingType = "UTF-8",
243 int lineWrapLength = 60) const;
245 //==============================================================================
246 /** Returns this element's tag type name.
248 E.g. for an element such as \<MOOSE legs="4" antlers="2">, this would return
249 "MOOSE".
251 @see hasTagName
253 inline const String& getTagName() const noexcept { return tagName; }
255 /** Tests whether this element has a particular tag name.
257 @param possibleTagName the tag name you're comparing it with
259 @see getTagName
261 bool hasTagName (const String& possibleTagName) const noexcept;
263 //==============================================================================
264 /** Returns the number of XML attributes this element contains.
266 E.g. for an element such as \<MOOSE legs="4" antlers="2">, this would
267 return 2.
269 int getNumAttributes() const noexcept;
271 /** Returns the name of one of the elements attributes.
273 E.g. for an element such as \<MOOSE legs="4" antlers="2">, then
274 getAttributeName(1) would return "antlers".
276 @see getAttributeValue, getStringAttribute
278 const String& getAttributeName (int attributeIndex) const noexcept;
280 /** Returns the value of one of the elements attributes.
282 E.g. for an element such as \<MOOSE legs="4" antlers="2">, then
283 getAttributeName(1) would return "2".
285 @see getAttributeName, getStringAttribute
287 const String& getAttributeValue (int attributeIndex) const noexcept;
289 //==============================================================================
290 // Attribute-handling methods..
292 /** Checks whether the element contains an attribute with a certain name. */
293 bool hasAttribute (const String& attributeName) const noexcept;
295 /** Returns the value of a named attribute.
297 @param attributeName the name of the attribute to look up
299 const String& getStringAttribute (const String& attributeName) const noexcept;
301 /** Returns the value of a named attribute.
303 @param attributeName the name of the attribute to look up
304 @param defaultReturnValue a value to return if the element doesn't have an attribute
305 with this name
307 String getStringAttribute (const String& attributeName,
308 const String& defaultReturnValue) const;
310 /** Compares the value of a named attribute with a value passed-in.
312 @param attributeName the name of the attribute to look up
313 @param stringToCompareAgainst the value to compare it with
314 @param ignoreCase whether the comparison should be case-insensitive
315 @returns true if the value of the attribute is the same as the string passed-in;
316 false if it's different (or if no such attribute exists)
318 bool compareAttribute (const String& attributeName,
319 const String& stringToCompareAgainst,
320 bool ignoreCase = false) const noexcept;
322 /** Returns the value of a named attribute as an integer.
324 This will try to find the attribute and convert it to an integer (using
325 the String::getIntValue() method).
327 @param attributeName the name of the attribute to look up
328 @param defaultReturnValue a value to return if the element doesn't have an attribute
329 with this name
330 @see setAttribute
332 int getIntAttribute (const String& attributeName,
333 int defaultReturnValue = 0) const;
335 /** Returns the value of a named attribute as floating-point.
337 This will try to find the attribute and convert it to an integer (using
338 the String::getDoubleValue() method).
340 @param attributeName the name of the attribute to look up
341 @param defaultReturnValue a value to return if the element doesn't have an attribute
342 with this name
343 @see setAttribute
345 double getDoubleAttribute (const String& attributeName,
346 double defaultReturnValue = 0.0) const;
348 /** Returns the value of a named attribute as a boolean.
350 This will try to find the attribute and interpret it as a boolean. To do this,
351 it'll return true if the value is "1", "true", "y", etc, or false for other
352 values.
354 @param attributeName the name of the attribute to look up
355 @param defaultReturnValue a value to return if the element doesn't have an attribute
356 with this name
358 bool getBoolAttribute (const String& attributeName,
359 bool defaultReturnValue = false) const;
361 /** Adds a named attribute to the element.
363 If the element already contains an attribute with this name, it's value will
364 be updated to the new value. If there's no such attribute yet, a new one will
365 be added.
367 Note that there are other setAttribute() methods that take integers,
368 doubles, etc. to make it easy to store numbers.
370 @param attributeName the name of the attribute to set
371 @param newValue the value to set it to
372 @see removeAttribute
374 void setAttribute (const String& attributeName,
375 const String& newValue);
377 /** Adds a named attribute to the element, setting it to an integer value.
379 If the element already contains an attribute with this name, it's value will
380 be updated to the new value. If there's no such attribute yet, a new one will
381 be added.
383 Note that there are other setAttribute() methods that take integers,
384 doubles, etc. to make it easy to store numbers.
386 @param attributeName the name of the attribute to set
387 @param newValue the value to set it to
389 void setAttribute (const String& attributeName,
390 int newValue);
392 /** Adds a named attribute to the element, setting it to a floating-point value.
394 If the element already contains an attribute with this name, it's value will
395 be updated to the new value. If there's no such attribute yet, a new one will
396 be added.
398 Note that there are other setAttribute() methods that take integers,
399 doubles, etc. to make it easy to store numbers.
401 @param attributeName the name of the attribute to set
402 @param newValue the value to set it to
404 void setAttribute (const String& attributeName,
405 double newValue);
407 /** Removes a named attribute from the element.
409 @param attributeName the name of the attribute to remove
410 @see removeAllAttributes
412 void removeAttribute (const String& attributeName) noexcept;
414 /** Removes all attributes from this element.
416 void removeAllAttributes() noexcept;
418 //==============================================================================
419 // Child element methods..
421 /** Returns the first of this element's sub-elements.
423 see getNextElement() for an example of how to iterate the sub-elements.
425 @see forEachXmlChildElement
427 XmlElement* getFirstChildElement() const noexcept { return firstChildElement; }
429 /** Returns the next of this element's siblings.
431 This can be used for iterating an element's sub-elements, e.g.
432 @code
433 XmlElement* child = myXmlDocument->getFirstChildElement();
435 while (child != nullptr)
437 ...do stuff with this child..
439 child = child->getNextElement();
441 @endcode
443 Note that when iterating the child elements, some of them might be
444 text elements as well as XML tags - use isTextElement() to work this
445 out.
447 Also, it's much easier and neater to use this method indirectly via the
448 forEachXmlChildElement macro.
450 @returns the sibling element that follows this one, or zero if this is the last
451 element in its parent
453 @see getNextElement, isTextElement, forEachXmlChildElement
455 inline XmlElement* getNextElement() const noexcept { return nextListItem; }
457 /** Returns the next of this element's siblings which has the specified tag
458 name.
460 This is like getNextElement(), but will scan through the list until it
461 finds an element with the given tag name.
463 @see getNextElement, forEachXmlChildElementWithTagName
465 XmlElement* getNextElementWithTagName (const String& requiredTagName) const;
467 /** Returns the number of sub-elements in this element.
469 @see getChildElement
471 int getNumChildElements() const noexcept;
473 /** Returns the sub-element at a certain index.
475 It's not very efficient to iterate the sub-elements by index - see
476 getNextElement() for an example of how best to iterate.
478 @returns the n'th child of this element, or 0 if the index is out-of-range
479 @see getNextElement, isTextElement, getChildByName
481 XmlElement* getChildElement (int index) const noexcept;
483 /** Returns the first sub-element with a given tag-name.
485 @param tagNameToLookFor the tag name of the element you want to find
486 @returns the first element with this tag name, or 0 if none is found
487 @see getNextElement, isTextElement, getChildElement
489 XmlElement* getChildByName (const String& tagNameToLookFor) const noexcept;
491 //==============================================================================
492 /** Appends an element to this element's list of children.
494 Child elements are deleted automatically when their parent is deleted, so
495 make sure the object that you pass in will not be deleted by anything else,
496 and make sure it's not already the child of another element.
498 @see getFirstChildElement, getNextElement, getNumChildElements,
499 getChildElement, removeChildElement
501 void addChildElement (XmlElement* newChildElement) noexcept;
503 /** Inserts an element into this element's list of children.
505 Child elements are deleted automatically when their parent is deleted, so
506 make sure the object that you pass in will not be deleted by anything else,
507 and make sure it's not already the child of another element.
509 @param newChildNode the element to add
510 @param indexToInsertAt the index at which to insert the new element - if this is
511 below zero, it will be added to the end of the list
512 @see addChildElement, insertChildElement
514 void insertChildElement (XmlElement* newChildNode,
515 int indexToInsertAt) noexcept;
517 /** Creates a new element with the given name and returns it, after adding it
518 as a child element.
520 This is a handy method that means that instead of writing this:
521 @code
522 XmlElement* newElement = new XmlElement ("foobar");
523 myParentElement->addChildElement (newElement);
524 @endcode
526 ..you could just write this:
527 @code
528 XmlElement* newElement = myParentElement->createNewChildElement ("foobar");
529 @endcode
531 XmlElement* createNewChildElement (const String& tagName);
533 /** Replaces one of this element's children with another node.
535 If the current element passed-in isn't actually a child of this element,
536 this will return false and the new one won't be added. Otherwise, the
537 existing element will be deleted, replaced with the new one, and it
538 will return true.
540 bool replaceChildElement (XmlElement* currentChildElement,
541 XmlElement* newChildNode) noexcept;
543 /** Removes a child element.
545 @param childToRemove the child to look for and remove
546 @param shouldDeleteTheChild if true, the child will be deleted, if false it'll
547 just remove it
549 void removeChildElement (XmlElement* childToRemove,
550 bool shouldDeleteTheChild) noexcept;
552 /** Deletes all the child elements in the element.
554 @see removeChildElement, deleteAllChildElementsWithTagName
556 void deleteAllChildElements() noexcept;
558 /** Deletes all the child elements with a given tag name.
560 @see removeChildElement
562 void deleteAllChildElementsWithTagName (const String& tagName) noexcept;
564 /** Returns true if the given element is a child of this one. */
565 bool containsChildElement (const XmlElement* possibleChild) const noexcept;
567 /** Recursively searches all sub-elements to find one that contains the specified
568 child element.
570 XmlElement* findParentElementOf (const XmlElement* elementToLookFor) noexcept;
572 //==============================================================================
573 /** Sorts the child elements using a comparator.
575 This will use a comparator object to sort the elements into order. The object
576 passed must have a method of the form:
577 @code
578 int compareElements (const XmlElement* first, const XmlElement* second);
579 @endcode
581 ..and this method must return:
582 - a value of < 0 if the first comes before the second
583 - a value of 0 if the two objects are equivalent
584 - a value of > 0 if the second comes before the first
586 To improve performance, the compareElements() method can be declared as static or const.
588 @param comparator the comparator to use for comparing elements.
589 @param retainOrderOfEquivalentItems if this is true, then items which the comparator
590 says are equivalent will be kept in the order in which they
591 currently appear in the array. This is slower to perform, but
592 may be important in some cases. If it's false, a faster algorithm
593 is used, but equivalent elements may be rearranged.
595 template <class ElementComparator>
596 void sortChildElements (ElementComparator& comparator,
597 bool retainOrderOfEquivalentItems = false)
599 const int num = getNumChildElements();
601 if (num > 1)
603 HeapBlock <XmlElement*> elems (num);
604 getChildElementsAsArray (elems);
605 sortArray (comparator, (XmlElement**) elems, 0, num - 1, retainOrderOfEquivalentItems);
606 reorderChildElements (elems, num);
610 //==============================================================================
611 /** Returns true if this element is a section of text.
613 Elements can either be an XML tag element or a secton of text, so this
614 is used to find out what kind of element this one is.
616 @see getAllText, addTextElement, deleteAllTextElements
618 bool isTextElement() const noexcept;
620 /** Returns the text for a text element.
622 Note that if you have an element like this:
624 @code<xyz>hello</xyz>@endcode
626 then calling getText on the "xyz" element won't return "hello", because that is
627 actually stored in a special text sub-element inside the xyz element. To get the
628 "hello" string, you could either call getText on the (unnamed) sub-element, or
629 use getAllSubText() to do this automatically.
631 Note that leading and trailing whitespace will be included in the string - to remove
632 if, just call String::trim() on the result.
634 @see isTextElement, getAllSubText, getChildElementAllSubText
636 const String& getText() const noexcept;
638 /** Sets the text in a text element.
640 Note that this is only a valid call if this element is a text element. If it's
641 not, then no action will be performed. If you're trying to add text inside a normal
642 element, you probably want to use addTextElement() instead.
644 void setText (const String& newText);
646 /** Returns all the text from this element's child nodes.
648 This iterates all the child elements and when it finds text elements,
649 it concatenates their text into a big string which it returns.
651 E.g. @code<xyz>hello <x>there</x> world</xyz>@endcode
652 if you called getAllSubText on the "xyz" element, it'd return "hello there world".
654 Note that leading and trailing whitespace will be included in the string - to remove
655 if, just call String::trim() on the result.
657 @see isTextElement, getChildElementAllSubText, getText, addTextElement
659 String getAllSubText() const;
661 /** Returns all the sub-text of a named child element.
663 If there is a child element with the given tag name, this will return
664 all of its sub-text (by calling getAllSubText() on it). If there is
665 no such child element, this will return the default string passed-in.
667 @see getAllSubText
669 String getChildElementAllSubText (const String& childTagName,
670 const String& defaultReturnValue) const;
672 /** Appends a section of text to this element.
674 @see isTextElement, getText, getAllSubText
676 void addTextElement (const String& text);
678 /** Removes all the text elements from this element.
680 @see isTextElement, getText, getAllSubText, addTextElement
682 void deleteAllTextElements() noexcept;
684 /** Creates a text element that can be added to a parent element.
686 static XmlElement* createTextElement (const String& text);
688 //==============================================================================
689 private:
690 struct XmlAttributeNode
692 XmlAttributeNode (const XmlAttributeNode& other) noexcept;
693 XmlAttributeNode (const String& name, const String& value) noexcept;
695 LinkedListPointer<XmlAttributeNode> nextListItem;
696 String name, value;
698 bool hasName (const String& name) const noexcept;
700 private:
701 XmlAttributeNode& operator= (const XmlAttributeNode&);
704 friend class XmlDocument;
705 friend class LinkedListPointer<XmlAttributeNode>;
706 friend class LinkedListPointer <XmlElement>;
707 friend class LinkedListPointer <XmlElement>::Appender;
709 LinkedListPointer <XmlElement> nextListItem;
710 LinkedListPointer <XmlElement> firstChildElement;
711 LinkedListPointer <XmlAttributeNode> attributes;
712 String tagName;
714 XmlElement (int) noexcept;
715 void copyChildrenAndAttributesFrom (const XmlElement& other);
716 void writeElementAsText (OutputStream& out, int indentationLevel, int lineWrapLength) const;
717 void getChildElementsAsArray (XmlElement**) const noexcept;
718 void reorderChildElements (XmlElement**, int) noexcept;
720 JUCE_LEAK_DETECTOR (XmlElement);
724 #endif // __JUCE_XMLELEMENT_JUCEHEADER__