/**
   * Process an MXMLTagData - this will write a String representation of the tag into the
   * StringWriter passed in. This will strip out any databinding expressions from the String, TODO:
   * databinding - add the databinding expressions as children of the MXMLXMLNode, and also record
   * what the TODO: target expressions for those are (these are the expressions to set the value in
   * the XML object when the TODO: PropertyChange event fires).
   */
  void processNode(MXMLTagData tag, StringWriter sw) {
    sw.write('<');
    if (tag.isCloseTag()) sw.write('/');
    sw.write(tag.getName());
    String tagPrefix = tag.getPrefix();

    // lookup the prefix in case it's defined elsewhere in the document outside the XML tag
    if (tagPrefix != null) lookupPrefix(tagPrefix, tag);

    List<MXMLTagAttributeData> attrs = getAttributes(tag);
    for (MXMLTagAttributeData attr : attrs) {
      sw.write(' ');
      sw.write(attr.getName());
      sw.write('=');
      sw.write('"');
      sw.write(attr.getRawValue());
      sw.write('"');

      // lookup the prefix in case it's defined outside the XML tag
      String prefix = attr.getPrefix();
      if (prefix != null) lookupPrefix(prefix, tag);
    }

    StringWriter childrenSW = new StringWriter();
    for (MXMLUnitData unit = tag.getFirstChildUnit();
        unit != null;
        unit = unit.getNextSiblingUnit()) {
      processNode(unit, childrenSW);
    }

    if (tag == rootTag) {
      // If we're the root tag, then add an xmlns for each prefix that was referenced by one of our
      // children, but was defined elsewhere in the document (like in the Application tag).
      for (String prefix : referencedPrefixes) {
        String uri = externalPrefixes.getNamespaceForPrefix(prefix);
        if (uri != null) {
          sw.write(" xmlns:");
          sw.write(prefix);
          sw.write("=\"");
          sw.write(uri);
          sw.write('\"');
        }
      }
    }
    if (tag.isEmptyTag()) {
      sw.write("/>");
    } else {
      sw.write('>');
    }
    sw.write(childrenSW.toString());

    MXMLTagData endTag = tag.findMatchingEndTag();
    if (endTag != null) {
      processNode(endTag, sw);
    }
  }
 /**
  * Helper to determine if a give MXMLUnitData is the only Text child of an MXMLTagData This
  * implies special, different processing from normal Text Datas.
  */
 private boolean isOnlyTextChild(MXMLUnitData child) {
   if (child instanceof MXMLTextData
       && ((MXMLTextData) child).getTextType() == IMXMLTextData.TextType.TEXT) {
     MXMLUnitData p = child.getParentUnitData();
     MXMLTagData parent = p instanceof MXMLTagData ? (MXMLTagData) p : null;
     if (parent != null) {
       return parent.getFirstChildUnit() == child && child.getNextSiblingUnit() == null;
     }
   }
   return false;
 }
  /**
   * Get the index of a text data. Grabs the parent, and iterates it's children to find out what the
   * index of the text data passed in should be
   */
  private int getIndexOfText(MXMLTextData text) {
    MXMLUnitData parent = text.getParentUnitData();

    MXMLTagData parentTag = parent instanceof MXMLTagData ? (MXMLTagData) parent : null;
    int index = 0;

    if (parentTag != null) {
      for (MXMLUnitData d = parentTag.getFirstChildUnit(); d != null; d = d.getNextSiblingUnit()) {
        if (d == text) break;
        else if (d instanceof MXMLTextData
            && ((MXMLTextData) d).getTextType() == IMXMLTextData.TextType.CDATA) ++index;
      }
    }
    return index;
  }