OpenShot Library | libopenshot-audio  0.1.9
juce_XmlElement.h
1 
2 /** @weakgroup juce_core-xml
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /** A handy macro to make it easy to iterate all the child elements in an XmlElement.
32 
33  The parentXmlElement should be a reference to the parent XML, and the childElementVariableName
34  will be the name of a pointer to each child element.
35 
36  E.g. @code
37  XmlElement* myParentXml = createSomeKindOfXmlDocument();
38 
39  forEachXmlChildElement (*myParentXml, child)
40  {
41  if (child->hasTagName ("FOO"))
42  doSomethingWithXmlElement (child);
43  }
44 
45  @endcode
46 
47  @see forEachXmlChildElementWithTagName
48 */
49 #define forEachXmlChildElement(parentXmlElement, childElementVariableName) \
50 \
51  for (auto* childElementVariableName = (parentXmlElement).getFirstChildElement(); \
52  childElementVariableName != nullptr; \
53  childElementVariableName = childElementVariableName->getNextElement())
54 
55 /** A macro that makes it easy to iterate all the child elements of an XmlElement
56  which have a specified tag.
57 
58  This does the same job as the forEachXmlChildElement macro, but only for those
59  elements that have a particular tag name.
60 
61  The parentXmlElement should be a reference to the parent XML, and the childElementVariableName
62  will be the name of a pointer to each child element. The requiredTagName is the
63  tag name to match.
64 
65  E.g. @code
66  XmlElement* myParentXml = createSomeKindOfXmlDocument();
67 
68  forEachXmlChildElementWithTagName (*myParentXml, child, "MYTAG")
69  {
70  // the child object is now guaranteed to be a <MYTAG> element..
71  doSomethingWithMYTAGElement (child);
72  }
73 
74  @endcode
75 
76  @see forEachXmlChildElement
77 */
78 #define forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \
79 \
80  for (auto* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \
81  childElementVariableName != nullptr; \
82  childElementVariableName = childElementVariableName->getNextElementWithTagName (requiredTagName))
83 
84 
85 //==============================================================================
86 /** Used to build a tree of elements representing an XML document.
87 
88  An XML document can be parsed into a tree of XmlElements, each of which
89  represents an XML tag structure, and which may itself contain other
90  nested elements.
91 
92  An XmlElement can also be converted back into a text document, and has
93  lots of useful methods for manipulating its attributes and sub-elements,
94  so XmlElements can actually be used as a handy general-purpose data
95  structure.
96 
97  Here's an example of parsing some elements: @code
98  // check we're looking at the right kind of document..
99  if (myElement->hasTagName ("ANIMALS"))
100  {
101  // now we'll iterate its sub-elements looking for 'giraffe' elements..
102  forEachXmlChildElement (*myElement, e)
103  {
104  if (e->hasTagName ("GIRAFFE"))
105  {
106  // found a giraffe, so use some of its attributes..
107 
108  String giraffeName = e->getStringAttribute ("name");
109  int giraffeAge = e->getIntAttribute ("age");
110  bool isFriendly = e->getBoolAttribute ("friendly");
111  }
112  }
113  }
114  @endcode
115 
116  And here's an example of how to create an XML document from scratch: @code
117  // create an outer node called "ANIMALS"
118  XmlElement animalsList ("ANIMALS");
119 
120  for (int i = 0; i < numAnimals; ++i)
121  {
122  // create an inner element..
123  XmlElement* giraffe = new XmlElement ("GIRAFFE");
124 
125  giraffe->setAttribute ("name", "nigel");
126  giraffe->setAttribute ("age", 10);
127  giraffe->setAttribute ("friendly", true);
128 
129  // ..and add our new element to the parent node
130  animalsList.addChildElement (giraffe);
131  }
132 
133  // now we can turn the whole thing into a text document..
134  String myXmlDoc = animalsList.createDocument (String());
135  @endcode
136 
137  @see XmlDocument
138 
139  @tags{Core}
140 */
142 {
143 public:
144  //==============================================================================
145  /** Creates an XmlElement with this tag name. */
146  explicit XmlElement (const String& tagName);
147 
148  /** Creates an XmlElement with this tag name. */
149  explicit XmlElement (const char* tagName);
150 
151  /** Creates an XmlElement with this tag name. */
152  explicit XmlElement (const Identifier& tagName);
153 
154  /** Creates an XmlElement with this tag name. */
155  explicit XmlElement (StringRef tagName);
156 
157  /** Creates an XmlElement with this tag name. */
159 
160  /** Creates a (deep) copy of another element. */
161  XmlElement (const XmlElement&);
162 
163  /** Creates a (deep) copy of another element. */
164  XmlElement& operator= (const XmlElement&);
165 
166  /** Move assignment operator */
167  XmlElement& operator= (XmlElement&&) noexcept;
168 
169  /** Move constructor */
170  XmlElement (XmlElement&&) noexcept;
171 
172  /** Deleting an XmlElement will also delete all of its child elements. */
173  ~XmlElement() noexcept;
174 
175  //==============================================================================
176  /** Compares two XmlElements to see if they contain the same text and attributes.
177 
178  The elements are only considered equivalent if they contain the same attributes
179  with the same values, and have the same sub-nodes.
180 
181  @param other the other element to compare to
182  @param ignoreOrderOfAttributes if true, this means that two elements with the
183  same attributes in a different order will be
184  considered the same; if false, the attributes must
185  be in the same order as well
186  */
187  bool isEquivalentTo (const XmlElement* other,
188  bool ignoreOrderOfAttributes) const noexcept;
189 
190  //==============================================================================
191  /** Returns an XML text document that represents this element.
192 
193  The string returned can be parsed to recreate the same XmlElement that
194  was used to create it.
195 
196  @param dtdToUse the DTD to add to the document
197  @param allOnOneLine if true, this means that the document will not contain any
198  linefeeds, so it'll be smaller but not very easy to read.
199  @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the
200  document
201  @param encodingType the character encoding format string to put into the xml
202  header
203  @param lineWrapLength the line length that will be used before items get placed on
204  a new line. This isn't an absolute maximum length, it just
205  determines how lists of attributes get broken up
206  @see writeToStream, writeToFile
207  */
208  String createDocument (StringRef dtdToUse,
209  bool allOnOneLine = false,
210  bool includeXmlHeader = true,
211  StringRef encodingType = "UTF-8",
212  int lineWrapLength = 60) const;
213 
214  /** Writes the document to a stream as UTF-8.
215 
216  @param output the stream to write to
217  @param dtdToUse the DTD to add to the document
218  @param allOnOneLine if true, this means that the document will not contain any
219  linefeeds, so it'll be smaller but not very easy to read.
220  @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the
221  document
222  @param encodingType the character encoding format string to put into the xml
223  header
224  @param lineWrapLength the line length that will be used before items get placed on
225  a new line. This isn't an absolute maximum length, it just
226  determines how lists of attributes get broken up
227  @see writeToFile, createDocument
228  */
229  void writeToStream (OutputStream& output,
230  StringRef dtdToUse,
231  bool allOnOneLine = false,
232  bool includeXmlHeader = true,
233  StringRef encodingType = "UTF-8",
234  int lineWrapLength = 60) const;
235 
236  /** Writes the element to a file as an XML document.
237 
238  To improve safety in case something goes wrong while writing the file, this
239  will actually write the document to a new temporary file in the same
240  directory as the destination file, and if this succeeds, it will rename this
241  new file as the destination file (overwriting any existing file that was there).
242 
243  @param destinationFile the file to write to. If this already exists, it will be
244  overwritten.
245  @param dtdToUse the DTD to add to the document
246  @param encodingType the character encoding format string to put into the xml
247  header
248  @param lineWrapLength the line length that will be used before items get placed on
249  a new line. This isn't an absolute maximum length, it just
250  determines how lists of attributes get broken up
251  @returns true if the file is written successfully; false if something goes wrong
252  in the process
253  @see createDocument
254  */
255  bool writeToFile (const File& destinationFile,
256  StringRef dtdToUse,
257  StringRef encodingType = "UTF-8",
258  int lineWrapLength = 60) const;
259 
260  //==============================================================================
261  /** Returns this element's tag type name.
262  E.g. for an element such as <MOOSE legs="4" antlers="2">, this would return "MOOSE".
263  @see hasTagName
264  */
265  const String& getTagName() const noexcept { return tagName; }
266 
267  /** Returns the namespace portion of the tag-name, or an empty string if none is specified. */
268  String getNamespace() const;
269 
270  /** Returns the part of the tag-name that follows any namespace declaration. */
271  String getTagNameWithoutNamespace() const;
272 
273  /** Tests whether this element has a particular tag name.
274  @param possibleTagName the tag name you're comparing it with
275  @see getTagName
276  */
277  bool hasTagName (StringRef possibleTagName) const noexcept;
278 
279  /** Tests whether this element has a particular tag name, ignoring any XML namespace prefix.
280  So a test for e.g. "xyz" will return true for "xyz" and also "foo:xyz", "bar::xyz", etc.
281  @see getTagName
282  */
283  bool hasTagNameIgnoringNamespace (StringRef possibleTagName) const;
284 
285  /** Changes this elements tag name.
286  @see getTagName
287  */
288  void setTagName (StringRef newTagName);
289 
290  //==============================================================================
291  /** Returns the number of XML attributes this element contains.
292 
293  E.g. for an element such as <MOOSE legs="4" antlers="2">, this would
294  return 2.
295  */
296  int getNumAttributes() const noexcept;
297 
298  /** Returns the name of one of the elements attributes.
299 
300  E.g. for an element such as <MOOSE legs="4" antlers="2">, then
301  getAttributeName(1) would return "antlers".
302 
303  @see getAttributeValue, getStringAttribute
304  */
305  const String& getAttributeName (int attributeIndex) const noexcept;
306 
307  /** Returns the value of one of the elements attributes.
308 
309  E.g. for an element such as <MOOSE legs="4" antlers="2">, then
310  getAttributeName(1) would return "2".
311 
312  @see getAttributeName, getStringAttribute
313  */
314  const String& getAttributeValue (int attributeIndex) const noexcept;
315 
316  //==============================================================================
317  // Attribute-handling methods..
318 
319  /** Checks whether the element contains an attribute with a certain name. */
320  bool hasAttribute (StringRef attributeName) const noexcept;
321 
322  /** Returns the value of a named attribute.
323  @param attributeName the name of the attribute to look up
324  */
325  const String& getStringAttribute (StringRef attributeName) const noexcept;
326 
327  /** Returns the value of a named attribute.
328  @param attributeName the name of the attribute to look up
329  @param defaultReturnValue a value to return if the element doesn't have an attribute
330  with this name
331  */
332  String getStringAttribute (StringRef attributeName, const String& defaultReturnValue) const;
333 
334  /** Compares the value of a named attribute with a value passed-in.
335 
336  @param attributeName the name of the attribute to look up
337  @param stringToCompareAgainst the value to compare it with
338  @param ignoreCase whether the comparison should be case-insensitive
339  @returns true if the value of the attribute is the same as the string passed-in;
340  false if it's different (or if no such attribute exists)
341  */
342  bool compareAttribute (StringRef attributeName,
343  StringRef stringToCompareAgainst,
344  bool ignoreCase = false) const noexcept;
345 
346  /** Returns the value of a named attribute as an integer.
347 
348  This will try to find the attribute and convert it to an integer (using
349  the String::getIntValue() method).
350 
351  @param attributeName the name of the attribute to look up
352  @param defaultReturnValue a value to return if the element doesn't have an attribute
353  with this name
354  @see setAttribute
355  */
356  int getIntAttribute (StringRef attributeName, int defaultReturnValue = 0) const;
357 
358  /** Returns the value of a named attribute as floating-point.
359 
360  This will try to find the attribute and convert it to a double (using
361  the String::getDoubleValue() method).
362 
363  @param attributeName the name of the attribute to look up
364  @param defaultReturnValue a value to return if the element doesn't have an attribute
365  with this name
366  @see setAttribute
367  */
368  double getDoubleAttribute (StringRef attributeName, double defaultReturnValue = 0.0) const;
369 
370  /** Returns the value of a named attribute as a boolean.
371 
372  This will try to find the attribute and interpret it as a boolean. To do this,
373  it'll return true if the value is "1", "true", "y", etc, or false for other
374  values.
375 
376  @param attributeName the name of the attribute to look up
377  @param defaultReturnValue a value to return if the element doesn't have an attribute
378  with this name
379  */
380  bool getBoolAttribute (StringRef attributeName, bool defaultReturnValue = false) const;
381 
382  /** Adds a named attribute to the element.
383 
384  If the element already contains an attribute with this name, it's value will
385  be updated to the new value. If there's no such attribute yet, a new one will
386  be added.
387 
388  Note that there are other setAttribute() methods that take integers,
389  doubles, etc. to make it easy to store numbers.
390 
391  @param attributeName the name of the attribute to set
392  @param newValue the value to set it to
393  @see removeAttribute
394  */
395  void setAttribute (const Identifier& attributeName, const String& newValue);
396 
397  /** Adds a named attribute to the element, setting it to an integer value.
398 
399  If the element already contains an attribute with this name, it's value will
400  be updated to the new value. If there's no such attribute yet, a new one will
401  be added.
402 
403  Note that there are other setAttribute() methods that take integers,
404  doubles, etc. to make it easy to store numbers.
405 
406  @param attributeName the name of the attribute to set
407  @param newValue the value to set it to
408  */
409  void setAttribute (const Identifier& attributeName, int newValue);
410 
411  /** Adds a named attribute to the element, setting it to a floating-point value.
412 
413  If the element already contains an attribute with this name, it's value will
414  be updated to the new value. If there's no such attribute yet, a new one will
415  be added.
416 
417  Note that there are other setAttribute() methods that take integers,
418  doubles, etc. to make it easy to store numbers.
419 
420  @param attributeName the name of the attribute to set
421  @param newValue the value to set it to
422  */
423  void setAttribute (const Identifier& attributeName, double newValue);
424 
425  /** Removes a named attribute from the element.
426 
427  @param attributeName the name of the attribute to remove
428  @see removeAllAttributes
429  */
430  void removeAttribute (const Identifier& attributeName) noexcept;
431 
432  /** Removes all attributes from this element. */
433  void removeAllAttributes() noexcept;
434 
435  //==============================================================================
436  // Child element methods..
437 
438  /** Returns the first of this element's sub-elements.
439  see getNextElement() for an example of how to iterate the sub-elements.
440  @see forEachXmlChildElement
441  */
442  XmlElement* getFirstChildElement() const noexcept { return firstChildElement; }
443 
444  /** Returns the next of this element's siblings.
445 
446  This can be used for iterating an element's sub-elements, e.g.
447  @code
448  XmlElement* child = myXmlDocument->getFirstChildElement();
449 
450  while (child != nullptr)
451  {
452  ...do stuff with this child..
453 
454  child = child->getNextElement();
455  }
456  @endcode
457 
458  Note that when iterating the child elements, some of them might be
459  text elements as well as XML tags - use isTextElement() to work this
460  out.
461 
462  Also, it's much easier and neater to use this method indirectly via the
463  forEachXmlChildElement macro.
464 
465  @returns the sibling element that follows this one, or a nullptr if
466  this is the last element in its parent
467 
468  @see getNextElement, isTextElement, forEachXmlChildElement
469  */
470  inline XmlElement* getNextElement() const noexcept { return nextListItem; }
471 
472  /** Returns the next of this element's siblings which has the specified tag
473  name.
474 
475  This is like getNextElement(), but will scan through the list until it
476  finds an element with the given tag name.
477 
478  @see getNextElement, forEachXmlChildElementWithTagName
479  */
480  XmlElement* getNextElementWithTagName (StringRef requiredTagName) const;
481 
482  /** Returns the number of sub-elements in this element.
483  @see getChildElement
484  */
485  int getNumChildElements() const noexcept;
486 
487  /** Returns the sub-element at a certain index.
488 
489  It's not very efficient to iterate the sub-elements by index - see
490  getNextElement() for an example of how best to iterate.
491 
492  @returns the n'th child of this element, or nullptr if the index is out-of-range
493  @see getNextElement, isTextElement, getChildByName
494  */
495  XmlElement* getChildElement (int index) const noexcept;
496 
497  /** Returns the first sub-element with a given tag-name.
498 
499  @param tagNameToLookFor the tag name of the element you want to find
500  @returns the first element with this tag name, or nullptr if none is found
501  @see getNextElement, isTextElement, getChildElement, getChildByAttribute
502  */
503  XmlElement* getChildByName (StringRef tagNameToLookFor) const noexcept;
504 
505  /** Returns the first sub-element which has an attribute that matches the given value.
506 
507  @param attributeName the name of the attribute to check
508  @param attributeValue the target value of the attribute
509  @returns the first element with this attribute value, or nullptr if none is found
510  @see getChildByName
511  */
512  XmlElement* getChildByAttribute (StringRef attributeName,
513  StringRef attributeValue) const noexcept;
514 
515  //==============================================================================
516  /** Appends an element to this element's list of children.
517 
518  Child elements are deleted automatically when their parent is deleted, so
519  make sure the object that you pass in will not be deleted by anything else,
520  and make sure it's not already the child of another element.
521 
522  Note that due to the XmlElement using a singly-linked-list, prependChildElement()
523  is an O(1) operation, but addChildElement() is an O(N) operation - so if
524  you're adding large number of elements, you may prefer to do so in reverse order!
525 
526  @see getFirstChildElement, getNextElement, getNumChildElements,
527  getChildElement, removeChildElement
528  */
529  void addChildElement (XmlElement* newChildElement) noexcept;
530 
531  /** Inserts an element into this element's list of children.
532 
533  Child elements are deleted automatically when their parent is deleted, so
534  make sure the object that you pass in will not be deleted by anything else,
535  and make sure it's not already the child of another element.
536 
537  @param newChildElement the element to add
538  @param indexToInsertAt the index at which to insert the new element - if this is
539  below zero, it will be added to the end of the list
540  @see addChildElement, insertChildElement
541  */
542  void insertChildElement (XmlElement* newChildElement,
543  int indexToInsertAt) noexcept;
544 
545  /** Inserts an element at the beginning of this element's list of children.
546 
547  Child elements are deleted automatically when their parent is deleted, so
548  make sure the object that you pass in will not be deleted by anything else,
549  and make sure it's not already the child of another element.
550 
551  Note that due to the XmlElement using a singly-linked-list, prependChildElement()
552  is an O(1) operation, but addChildElement() is an O(N) operation - so if
553  you're adding large number of elements, you may prefer to do so in reverse order!
554 
555  @see addChildElement, insertChildElement
556  */
557  void prependChildElement (XmlElement* newChildElement) noexcept;
558 
559  /** Creates a new element with the given name and returns it, after adding it
560  as a child element.
561 
562  This is a handy method that means that instead of writing this:
563  @code
564  XmlElement* newElement = new XmlElement ("foobar");
565  myParentElement->addChildElement (newElement);
566  @endcode
567 
568  ..you could just write this:
569  @code
570  XmlElement* newElement = myParentElement->createNewChildElement ("foobar");
571  @endcode
572  */
573  XmlElement* createNewChildElement (StringRef tagName);
574 
575  /** Replaces one of this element's children with another node.
576 
577  If the current element passed-in isn't actually a child of this element,
578  this will return false and the new one won't be added. Otherwise, the
579  existing element will be deleted, replaced with the new one, and it
580  will return true.
581  */
582  bool replaceChildElement (XmlElement* currentChildElement,
583  XmlElement* newChildNode) noexcept;
584 
585  /** Removes a child element.
586 
587  @param childToRemove the child to look for and remove
588  @param shouldDeleteTheChild if true, the child will be deleted, if false it'll
589  just remove it
590  */
591  void removeChildElement (XmlElement* childToRemove,
592  bool shouldDeleteTheChild) noexcept;
593 
594  /** Deletes all the child elements in the element.
595  @see removeChildElement, deleteAllChildElementsWithTagName
596  */
597  void deleteAllChildElements() noexcept;
598 
599  /** Deletes all the child elements with a given tag name.
600  @see removeChildElement
601  */
602  void deleteAllChildElementsWithTagName (StringRef tagName) noexcept;
603 
604  /** Returns true if the given element is a child of this one. */
605  bool containsChildElement (const XmlElement* possibleChild) const noexcept;
606 
607  /** Recursively searches all sub-elements of this one, looking for an element
608  which is the direct parent of the specified element.
609 
610  Because elements don't store a pointer to their parent, if you have one
611  and need to find its parent, the only way to do so is to exhaustively
612  search the whole tree for it.
613 
614  If the given child is found somewhere in this element's hierarchy, then
615  this method will return its parent. If not, it will return nullptr.
616  */
617  XmlElement* findParentElementOf (const XmlElement* childToSearchFor) noexcept;
618 
619  //==============================================================================
620  /** Sorts the child elements using a comparator.
621 
622  This will use a comparator object to sort the elements into order. The object
623  passed must have a method of the form:
624  @code
625  int compareElements (const XmlElement* first, const XmlElement* second);
626  @endcode
627 
628  ..and this method must return:
629  - a value of < 0 if the first comes before the second
630  - a value of 0 if the two objects are equivalent
631  - a value of > 0 if the second comes before the first
632 
633  To improve performance, the compareElements() method can be declared as static or const.
634 
635  @param comparator the comparator to use for comparing elements.
636  @param retainOrderOfEquivalentItems if this is true, then items which the comparator
637  says are equivalent will be kept in the order in which they
638  currently appear in the array. This is slower to perform, but
639  may be important in some cases. If it's false, a faster algorithm
640  is used, but equivalent elements may be rearranged.
641  */
642  template <class ElementComparator>
643  void sortChildElements (ElementComparator& comparator,
644  bool retainOrderOfEquivalentItems = false)
645  {
646  auto num = getNumChildElements();
647 
648  if (num > 1)
649  {
650  HeapBlock<XmlElement*> elems (num);
651  getChildElementsAsArray (elems);
652  sortArray (comparator, (XmlElement**) elems, 0, num - 1, retainOrderOfEquivalentItems);
653  reorderChildElements (elems, num);
654  }
655  }
656 
657  //==============================================================================
658  /** Returns true if this element is a section of text.
659 
660  Elements can either be an XML tag element or a section of text, so this
661  is used to find out what kind of element this one is.
662 
663  @see getAllText, addTextElement, deleteAllTextElements
664  */
665  bool isTextElement() const noexcept;
666 
667  /** Returns the text for a text element.
668 
669  Note that if you have an element like this:
670 
671  @code<xyz>hello</xyz>@endcode
672 
673  then calling getText on the "xyz" element won't return "hello", because that is
674  actually stored in a special text sub-element inside the xyz element. To get the
675  "hello" string, you could either call getText on the (unnamed) sub-element, or
676  use getAllSubText() to do this automatically.
677 
678  Note that leading and trailing whitespace will be included in the string - to remove
679  if, just call String::trim() on the result.
680 
681  @see isTextElement, getAllSubText, getChildElementAllSubText
682  */
683  const String& getText() const noexcept;
684 
685  /** Sets the text in a text element.
686 
687  Note that this is only a valid call if this element is a text element. If it's
688  not, then no action will be performed. If you're trying to add text inside a normal
689  element, you probably want to use addTextElement() instead.
690  */
691  void setText (const String& newText);
692 
693  /** Returns all the text from this element's child nodes.
694 
695  This iterates all the child elements and when it finds text elements,
696  it concatenates their text into a big string which it returns.
697 
698  E.g. @code<xyz>hello <x>there</x> world</xyz>@endcode
699  if you called getAllSubText on the "xyz" element, it'd return "hello there world".
700 
701  Note that leading and trailing whitespace will be included in the string - to remove
702  if, just call String::trim() on the result.
703 
704  @see isTextElement, getChildElementAllSubText, getText, addTextElement
705  */
706  String getAllSubText() const;
707 
708  /** Returns all the sub-text of a named child element.
709 
710  If there is a child element with the given tag name, this will return
711  all of its sub-text (by calling getAllSubText() on it). If there is
712  no such child element, this will return the default string passed-in.
713 
714  @see getAllSubText
715  */
716  String getChildElementAllSubText (StringRef childTagName,
717  const String& defaultReturnValue) const;
718 
719  /** Appends a section of text to this element.
720  @see isTextElement, getText, getAllSubText
721  */
722  void addTextElement (const String& text);
723 
724  /** Removes all the text elements from this element.
725  @see isTextElement, getText, getAllSubText, addTextElement
726  */
727  void deleteAllTextElements() noexcept;
728 
729  /** Creates a text element that can be added to a parent element. */
730  static XmlElement* createTextElement (const String& text);
731 
732  /** Checks if a given string is a valid XML name */
733  static bool isValidXmlName (StringRef possibleName) noexcept;
734 
735  //==============================================================================
736 private:
737  struct XmlAttributeNode
738  {
739  XmlAttributeNode (const XmlAttributeNode&) noexcept;
740  XmlAttributeNode (const Identifier&, const String&) noexcept;
742 
744  Identifier name;
745  String value;
746 
747  private:
748  XmlAttributeNode& operator= (const XmlAttributeNode&) = delete;
749  };
750 
751  friend class XmlDocument;
752  friend class LinkedListPointer<XmlAttributeNode>;
753  friend class LinkedListPointer<XmlElement>;
754  friend class LinkedListPointer<XmlElement>::Appender;
755  friend class NamedValueSet;
756 
757  LinkedListPointer<XmlElement> nextListItem;
758  LinkedListPointer<XmlElement> firstChildElement;
759  LinkedListPointer<XmlAttributeNode> attributes;
760  String tagName;
761 
762  XmlElement (int) noexcept;
763  void copyChildrenAndAttributesFrom (const XmlElement&);
764  void writeElementAsText (OutputStream&, int indentationLevel, int lineWrapLength) const;
765  void getChildElementsAsArray (XmlElement**) const noexcept;
766  void reorderChildElements (XmlElement**, int) noexcept;
767  XmlAttributeNode* getAttribute (StringRef) const noexcept;
768 
769  // Sigh.. L"" or _T("") string literals are problematic in general, and really inappropriate
770  // for XML tags. Use a UTF-8 encoded literal instead, or if you're really determined to use
771  // UTF-16, cast it to a String and use the other constructor.
772  XmlElement (const wchar_t*) = delete;
773 
774  JUCE_LEAK_DETECTOR (XmlElement)
775 };
776 
777 } // namespace juce
778 
779 /** @}*/
Parses a text-based XML document and creates an XmlElement object from it.
#define JUCE_API
This macro is added to all JUCE public class declarations.
Represents a string identifier, designed for accessing properties by name.
A simple class for holding temporary references to a string literal or String.
Used to build a tree of elements representing an XML document.
Very simple container class to hold a pointer to some data on the heap.
The JUCE String class!
Definition: juce_String.h:42
Holds a set of named var objects.
XmlElement * getNextElement() const noexcept
Returns the next of this element&#39;s siblings.
void sortChildElements(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false)
Sorts the child elements using a comparator.
Represents a local file or directory.
Definition: juce_File.h:44
The base class for streams that write data to some kind of destination.
XmlElement * getFirstChildElement() const noexcept
Returns the first of this element&#39;s sub-elements.
const String & getTagName() const noexcept
Returns this element&#39;s tag type name.
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...