/// <summary> Write the attributes of a SifElement to the output stream</summary> /// <param name="o">The SifElement whose attributes are to be written /// </param> private void WriteAttributes(SifElement o) { // TODO: We need to make sure the GetFields() API returns a usable collection ICollection <SimpleField> fields = fFormatter.GetFields(o, fVersion); foreach (SimpleField f in fields) { IElementVersionInfo evi = f.ElementDef.GetVersionInfo(fVersion); if (evi != null && evi.IsAttribute) { // Null attribute values are not supported in SIF, unlike // element values, which can be represented with xs:nil SifSimpleType sst = f.SifValue; if (sst.RawValue != null) { String tag = evi.Tag; Boolean handled = false; if (tag.StartsWith("x")) { if (evi.Tag.Equals("xml:lang")) { fWriter.WriteAttributeString("xml", "lang", null, sst.ToString(fFormatter)); } else if (evi.Tag.Equals("xsi:type")) { fWriter.WriteAttributeString("type", XmlSchema.InstanceNamespace, sst.ToString(fFormatter)); } handled = true; } if (!handled) { fWriter.WriteStartAttribute(evi.Tag, string.Empty); fWriter.WriteString(sst.ToString(fFormatter)); fWriter.WriteEndAttribute(); } } } } if (fSerializeIds && o.XmlId != null) { fWriter.WriteAttributeString("id", XML_NAMESPACE, o.XmlId); } }
private void ParseLegacyXML( XmlReader reader, SifVersion version, IZone zone, SifElement currentElement, SifFormatter formatter, String xmlName) { bool handled = false; // Determine if any surrogate formatters that are defined as children // of the current element can resolve it // NOTE: Until we fix this in the ADK, elements from the common package loose their // metadata information that was originally defined. IElementDef currentDef = currentElement.ElementDef; IList <IElementDef> children = currentDef.Children; if (children == null || children.Count == 0) { // try to get the actual element def // WARNING! this is somewhat of a hack until // we get support for what we need in the ADK metadata try { SifElement copy = (SifElement)ClassFactory.CreateInstance(currentDef.FQClassName); children = copy.ElementDef.Children; } catch (Exception cnfe) { throw new SifException( SifErrorCategoryCode.Xml, SifErrorCodes.XML_GENERIC_VALIDATION_3, "Unable to parse" + xmlName + " " + version.ToString() + cnfe.Message, zone); } } using (XmlReader subtreeReader = reader.ReadSubtree()) { subtreeReader.Read(); foreach (IElementDef candidate in children) { if (candidate.EarliestVersion.CompareTo(version) > 0) { continue; } IElementVersionInfo evi = candidate.GetVersionInfo(version); if (evi != null) { IRenderSurrogate rs = evi.GetSurrogate(); if (rs != null) { try { bool surrogateHandled = rs.ReadRaw(subtreeReader, version, currentElement, formatter); if (surrogateHandled) { handled = true; break; } } catch (AdkTypeParseException e) { HandleTypeParseException("Unable to parse element or attribute value: " + e.Message, e, zone); handled = true; break; } catch (AdkParsingException e) { throw new SifException(SifErrorCategoryCode.Xml, SifErrorCodes.XML_GENERIC_VALIDATION_3, "unable to parse xml: " + e.Message + version.ToString(), zone); } } } } subtreeReader.Close(); } // advance to the next tag reader.Read(); if (!handled) { String _tag = currentElement != null ? currentElement.ElementDef.Name + "/" + xmlName : xmlName; throw new SifException( SifErrorCategoryCode.Xml, SifErrorCodes.XML_GENERIC_VALIDATION_3, "Unknown element or attribute", _tag + " is not a recognized element of SIF " + version.ToString(), zone); } }
private SifElement ParseElementStream(XmlReader reader, SifVersion version, IDtd dtd, IZone zone, SifParserFlags flags) { bool legacyParse = version.CompareTo(SifVersion.SIF20) < 0; // The current SIFElement being parsed SifElement currentElement = null; // The actual tag name of the current element SifFormatter formatter = Adk.Dtd.GetFormatter(version); reader.MoveToContent(); bool doneParsing = false; while (!(reader.EOF || doneParsing)) { switch (reader.NodeType) { case XmlNodeType.Element: if (reader.LocalName == "SIF_Message") { // Special case for embedded SIF_Message envelopes if ((flags & SifParserFlags.ExpectInnerEnvelope) != 0) { SifElement msgElement = ReadSIFMessageElement(reader, dtd, zone, SifParserFlags.None, version); currentElement.AddChild(msgElement); currentElement = msgElement; } else { throw new AdkParsingException ("Unexpected SIF_Message encountered in parsing", zone); } } else { String xmlName = reader.LocalName; if (xmlName == "Teacher") { Console.WriteLine("Ready to break"); } IElementDef foundDef = LookupElementDef(currentElement, reader, dtd, version, zone); if (foundDef == null) { if (legacyParse) { ParseLegacyXML(reader, version, zone, currentElement, formatter, xmlName); continue; } else if (currentElement != null && currentElement.ElementDef.Name.Equals("XMLData")) { // Parse this into a DOM and set on the XMLData // element XmlReader nestedReader = reader.ReadSubtree(); XmlDocument doc = new XmlDocument(); doc.Load(nestedReader); ((XMLData)currentElement).Xml = doc; continue; } else { String _tag = currentElement != null ? currentElement.ElementDef.Name + "/" + xmlName : xmlName; throw new SifException(SifErrorCategoryCode.Xml, SifErrorCodes.XML_GENERIC_VALIDATION_3, "Unknown element or attribute", _tag + " is not a recognized element of SIF " + version.ToString(), zone); } } if (legacyParse) { IElementVersionInfo evi = foundDef.GetVersionInfo(version); if (evi != null) { IRenderSurrogate rs = evi.GetSurrogate(); if (rs != null) { using (XmlReader subtreeReader = reader.ReadSubtree()) { bool shouldContinue = true; subtreeReader.Read(); try { shouldContinue = rs.ReadRaw(subtreeReader, version, currentElement, formatter); } catch (AdkTypeParseException atpe) { HandleTypeParseException("Unable to parse value: " + atpe.Message, atpe, zone); } subtreeReader.Close(); // advance to the next tag reader.Read(); if (shouldContinue) { continue; } else { throw new SifException(SifErrorCategoryCode.Xml, SifErrorCodes.XML_GENERIC_VALIDATION_3, "Unknown element or attribute", reader.LocalName + " was not able to be parsed by " + rs, zone); } } } } } if (foundDef.Field) { SetFieldValueFromElement (foundDef, currentElement, reader, version, formatter, zone); // Advance to the next tag do { reader.Read(); } while ( !(reader.EOF || reader.NodeType == XmlNodeType.Element || reader.NodeType == XmlNodeType.EndElement)); continue; } else if (reader.IsEmptyElement) { // The .Net XmlReader does not return an EndElement event for // tags with empty content. Therefore, this region of the code is // slightly different from Java ReadSifElementFromElementNode(foundDef, reader, dtd, currentElement, formatter, version, zone); } else { currentElement = ReadSifElementFromElementNode(foundDef, reader, dtd, currentElement, formatter, version, zone); } } break; case XmlNodeType.Text: if (currentElement.ElementDef.HasSimpleContent) { SetFieldValueFromElement(currentElement.ElementDef, currentElement, reader, version, formatter, zone); // The XML Reader cursor is automatically advanced by this method, so we // need to continue on without calling read() continue; } break; case XmlNodeType.EndElement: if (currentElement.Parent != null) { currentElement = (SifElement)currentElement.Parent; while (legacyParse && currentElement.ElementDef.IsCollapsed(version)) { currentElement = (SifElement)currentElement.Parent; } } if (reader.LocalName == "SIF_Message") { // We need to return here. If we let the reader keep reading, and we are reading an embedded // SIF_Message, it will keep parsing the end tags and not let the stack of SifElement objects // propertly unwind. We're done anyway. doneParsing = true; } break; } // Advance the cursor reader.Read(); } if (currentElement == null) { return(null); } else { // Now, unwind and pop off the top element parsed Element top = currentElement; Element current; while ((current = top.Parent) != null) { top = current; } return((SifElement)top); } }