Manipulating elements and values

To get the child elements of an element, use the Children property, which contains a list (java.util.List<XmlElement>) of elements. If this XML element is an XSD-based type, you must prefix the property name with a $ ($Children in this case).

If the element has no child elements, there are two possibilities:

  • If the element has no text content, the Children property contains an empty list.
  • If the element has has text content, the Children property is null.

To add a child element, call the parent element’s addChild method and pass the child element as a parameter.

For example, in myschema.xsd (see XSD generated type examples):

  • The element named Child1 has the default type (xsd:anyType).
  • The element named Child2 has the simple type xsd:int. If the integer value is empty or null, the XML will not validate.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Element1">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Child1"/>  <!-- default type is xsd:anyType -->
        <xsd:element name="Child2" type="xsd:int"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

If you have a reference to an XML element of a simple type, you can set its value by assigning its SimpleValue property to a subclass of XmlSimpleValue. If you are using an XSD, add the dollar sign prefix: $SimpleValue. For example, the code used in XSD generated type examples can be modified so an integer value is assigned to Child1 using the static XmlSimpleValue.makeIntegerInstance method:

uses examples.pl.gosu.xml.myschema.Element1
var xml = Element1()
var child1 = xml.Child1                                        // Child1 has type anyType (the default when a type is not specified).
var child2 = xml.Child2                                        
xml.Child1.$SimpleValue = XmlSimpleValue.makeIntegerInstance(55) // Set the XML property as an integer type.
xml.Child2 = 5                                                    
var child2Elem = xml.Child2_elem
xml.print()                                                      // Display the entire element
child2Elem.print()                                               // Display the Child2 lower-level element

To set a simple value such as an integer value for an element, use one of the following approaches:

  • Set the value in the SimpleValue property to a subclass of XmlSimpleValue. This allows you to directly create the simple value that Gosu stores in the pre-serialized graph of XML elements. If the content is on an XSD type, specify the property name with the dollar sign prefix: $SimpleValue. To create an instance of the XmlSimpleValue of the appropriate type, call one of the static make methods belonging to the XmlSimpleValue class. For example, call the makeIntInstance method and pass it an Integer. It returns an XmlSimpleValue instance that contains an integer. In memory, Gosu stores this information as a non-serialized value. When exporting to a byte array or using the debugging print method, Gosu serializes the XmlSimpleValue into bytes or encoded text.
  • To create simple text content, which is a text simple value, set the element’s Text property to a String value. If the content is on an XSD type, specify the property name with the dollar sign prefix: $Text (as shown in XSD generated type examples).
  • If you are using an XSD, you can set the natural value in the Value property. If the content is on an XSD type, specify the property name with the dollar sign prefix ($Value). For example, use natural-looking code like xml.Child2.$Value = 5. If you are using an XSD and have non-text content, this approach tends to result in more natural-looking Gosu code than creating instances of XmlSimpleValue.
  • If you are using an XSD, Gosu provides a syntax to get and set child values with simple types. For example, set numbers and dates from an element’s parent element using natural syntax using the child element name as a property accessor. Using this syntax, you access the child element’s simple value with readable code. For example, xml.Child2 = 5.

Example

The following Gosu code adds two child elements, sets the value of an element using the Value property and the SimpleValue property, and then prints the results. In this example, we use XSD types, so we must specify the special property names with the dollar sign prefix: $Value and $SimpleValue.

uses examples.pl.gosu.xml.myschema.Element1
uses examples.pl.gosu.xml.myschema.anonymous.elements.Element1_Child1
uses examples.pl.gosu.xml.myschema.anonymous.elements.Element1_Child2
uses gw.xml.XmlSimpleValue

// Create a new element whose type is in the namespace of the XSD.
var xml = new Element1()
var c = xml.$Children // returns an empty list of type List<XmlElement>
print("Children " + c.Count + c)
print("")

// Create a new CHILD element that is legal in the XSD, and add it as child.
var c1 = new Element1_Child1()
xml.addChild(c1)

// Create a new CHILD element that is legal in the XSD, and add it as child.
var c2 = new Element1_Child2()
xml.addChild(c2)    // Add the child element.
print("before set: " + c2.$Value) // prints "null" -- it is uninitialized

c2.$SimpleValue = XmlSimpleValue.makeIntegerInstance(5)    // set value for c2
print("after set with $SimpleValue: " + c2.$SimpleValue)

c2.$SimpleValue = XmlSimpleValue.makeIntegerInstance(7)    // update value for c2
print("after update with $Simplevalue: " + c2.$SimpleValue)
print("")

c = xml.$Children // Return a list of two child elements
print("Children " + c.Count + c)
xml.print()

print("")

This code prints the following:

Children 0[]

before set: null
after set with $SimpleValue: Simple value (java.math.BigInteger): 5
after update with $Simplevalue: Simple value (java.math.BigInteger): 7

Children 2[examples.pl.gosu.xml.myschema.anonymous.elements.Element1_Child1 instance, 
examples.pl.gosu.xml.myschema.anonymous.elements.Element1_Child2 instance]

<?xml version="1.0"?>
<Element1>
  <Child1/>
  <Child2>7</Child2>
</Element1>

Note that the Child2 element contains the integer as text data in the serialized XML export since Gosu does not serialize the simple types to bytes (or a String) until serialization. In this example, the final print statement serializes the element and all its subelements.

Getting child elements by name

To iterate through a List of child elements to find data, use the Children property described earlier in this topic. In some cases you can use the Gosu enhancements on lists to locate the items you want.

To search for a child element by its name, use the XML element's getChild() method if you expect only one match, or its getChildren method if you expect multiple matches:
  • getChild(QName) – Searches the content list for a single child with the specified QName. An alternative method signature takes a String value for the local part name. For that method signature, Gosu and internally creates a QName with an empty namespace and the specified local part name. This method requires there to be exactly one child with this name. If there are multiple matches, the method throws an exception. In such cases use the getChildren method instead.
  • getChildren(QName) : List – Searches the content list for all children with the specified QName name. An alternative method signature takes a String value for the local part name. For that method signature, Gosu internally creates a QName with an empty namespace and the specified local part name.

Reusing the code from the previous example, add the following lines to get the child elements by name:

// Get a child using the empty namespce by passing a String.
var getChild1 = xml.getChild("Child1");

// Get a child using a QName, and "reuse" the namespace of a previous node.
var getChild2 = xml.getChild(getChild1. $Namespace.qualify("Child2"))

print("getChild1: " + getChild1)
print("getChild2: " + getChild2)

print("UTF String: " + getChild2.asUTFString())

This code prints the following:

getChild1: examples.pl.gosu.xml.myschema.anonymous.elements.Element1_Child1 instance
getChild2: examples.pl.gosu.xml.myschema.anonymous.elements.Element1_Child2 instance
UTF String: <?xml version="1.0"?>
<Child2>5</Child2>

Removing child elements by name

To remove child elements, use the XML element's removeChild method if you expect only one match, or its removeChildren method if you expect multiple matches:
removeChild(QName) : XmlElement
Removes the child with the specified QName. An alternative method signature takes a String value for the local part name. For that method signature, Gosu internally creates a QName with an empty namespace and the specified local part name.
removeChildren(QName) : List<XmlElement>
Removes the child with the specified QName name. An alternative method signature takes a String value for the local part name. For that method signature, Gosu internally creates a QName with an empty namespace and the specified local part name.

See also