/// <summary> /// Given an XML Node creates the relevant RDF/XML Events for it and recurses as necessary /// </summary> /// <param name="context">Parser Context</param> /// <param name="node">The Node to create Event(s) from</param> /// <param name="parent">The Parent Node of the given Node</param> /// <returns></returns> private ElementEvent GenerateEvents(RdfXmlParserContext context, XmlNode node, IRdfXmlEvent parent) { // Get the Base Uri String baseUri = String.Empty; if (parent is ElementEvent) { baseUri = ((ElementEvent)parent).BaseUri; } // Create an ElementEvent for the Node ElementEvent element = new ElementEvent(node.LocalName, node.Prefix, baseUri, node.OuterXml); // Set the initial Language from the Parent ElementEvent parentEl = (ElementEvent)parent; element.Language = parentEl.Language; #region Attribute Processing // Iterate over Attributes bool parseTypeLiteral = false; foreach (XmlAttribute attr in node.Attributes) { // Watch out for special attributes if (attr.Name == "xml:lang") { // Set Language element.Language = attr.Value; } else if (attr.Name == "xml:base") { // Set Base Uri if (RdfXmlSpecsHelper.IsAbsoluteURI(attr.Value)) { // Absolute Uri element.BaseUri = attr.Value; } else if (!element.BaseUri.Equals(String.Empty)) { // Relative Uri with a Base Uri to resolve against // element.BaseUri += attr.Value; element.BaseUri = Tools.ResolveUri(attr.Value, element.BaseUri); } else { // Relative Uri with no Base Uri throw new RdfParseException("Cannot resolve a Relative Base URI since there is no in-scope Base URI"); } } else if (attr.Prefix == "xmlns") { // Register a Namespace String uri; if (attr.Value.StartsWith("http://")) { // Absolute Uri uri = attr.Value; } else if (!element.BaseUri.Equals(String.Empty)) { // Relative Uri with a Base Uri to resolve against // uri = element.BaseUri + attr.Value; uri = Tools.ResolveUri(attr.Value, element.BaseUri); } else { // Relative Uri with no Base Uri throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI"); } NamespaceAttributeEvent ns = new NamespaceAttributeEvent(attr.LocalName, uri, attr.OuterXml); element.NamespaceAttributes.Add(ns); } else if (attr.Prefix == String.Empty && attr.Name == "xmlns") { // Register a Default Namespace (Empty Prefix) String uri; if (attr.Value.StartsWith("http://")) { // Absolute Uri uri = attr.Value; } else if (!element.BaseUri.Equals(String.Empty)) { // Relative Uri with a Base Uri to resolve against // uri = element.BaseUri + attr.Value; uri = Tools.ResolveUri(attr.Value, element.BaseUri); } else { // Relative Uri with no Base Uri throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI"); } NamespaceAttributeEvent ns = new NamespaceAttributeEvent(String.Empty, uri, attr.OuterXml); element.NamespaceAttributes.Add(ns); } else if (attr.Prefix == "xml" || (attr.Prefix == String.Empty && attr.LocalName.StartsWith("xml"))) { // Ignore other Reserved XML Names } else if (attr.Name == "rdf:parseType" && attr.Value == "Literal") { // Literal Parse Type parseTypeLiteral = true; // Create the Attribute AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml); element.Attributes.Add(attrEvent); // Set ParseType property correctly element.ParseType = RdfXmlParseType.Literal; } else if (attr.Name == "rdf:parseType") { // Some other Parse Type // Create the Attribute AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml); element.Attributes.Add(attrEvent); // Set the ParseType property correctly if (attr.Value == "Resource") { element.ParseType = RdfXmlParseType.Resource; } else if (attr.Value == "Collection") { element.ParseType = RdfXmlParseType.Collection; } else { // Have to assume Literal element.ParseType = RdfXmlParseType.Literal; parseTypeLiteral = true; // Replace the Parse Type attribute with one saying it is Literal element.Attributes.Remove(attrEvent); attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, "Literal", attr.OuterXml); } } else { // Normal Attribute which we generate an Event from AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml); element.Attributes.Add(attrEvent); } } // Validate generated Attributes for Namespace Confusion and URIRef encoding foreach (AttributeEvent a in element.Attributes) { // Namespace Confusion should only apply to Attributes without a Namespace specified if (a.Namespace.Equals(String.Empty)) { if (RdfXmlSpecsHelper.IsAmbigiousAttributeName(a.LocalName)) { // Can't use any of the RDF terms that mandate the rdf: prefix without it throw ParserHelper.Error("An Attribute with an ambigious name '" + a.LocalName + "' was encountered. The following attribute names MUST have the rdf: prefix - about, aboutEach, ID, bagID, type, resource, parseType", element); } } // URIRef encoding check if (!RdfXmlSpecsHelper.IsValidUriRefEncoding(a.Value)) { throw ParserHelper.Error("An Attribute with an incorrectly encoded URIRef was encountered, URIRef's must be encoded in Unicode Normal Form C", a); } } #endregion // Don't proceed if Literal Parse Type is on if (parseTypeLiteral) { // Generate an XMLLiteral from its Inner Xml (if any) TypedLiteralEvent lit = new TypedLiteralEvent(node.InnerXml.Normalize(), RdfSpecsHelper.RdfXmlLiteral, node.InnerXml); element.Children.Add(lit); return(element); } // Are there Child Nodes? if (node.HasChildNodes) { // Take different actions depending on the Number and Type of Child Nodes if (node.ChildNodes.Count > 1) { // Multiple Child Nodes // Iterate over Child Nodes foreach (XmlNode child in node.ChildNodes) { // Ignore Irrelevant Node Types if (IsIgnorableNode(child)) { continue; } // Generate an Event for the Child Node ElementEvent childEvent = GenerateEvents(context, child, element); element.Children.Add(childEvent); } } else if (node.ChildNodes[0].NodeType == XmlNodeType.Text) { // Single Child which is a Text Node // Generate a Text Event TextEvent text = new TextEvent(node.InnerText.Normalize(), node.OuterXml); element.Children.Add(text); } else if (node.ChildNodes[0].NodeType == XmlNodeType.CDATA) { // Single Child which is a CData Node TextEvent text = new TextEvent(node.InnerXml.Normalize(), node.OuterXml); element.Children.Add(text); } else { // Single Child which is not a Text Node // Recurse on the single Child Node if (!IsIgnorableNode(node.ChildNodes[0])) { ElementEvent childEvent = GenerateEvents(context, node.ChildNodes[0], element); element.Children.Add(childEvent); } } } return(element); }
/// <summary> /// Given an XML Node creates the relevant RDF/XML Events for it and recurses as necessary /// </summary> /// <param name="context">Parser Context</param> /// <param name="node">The Node to create Event(s) from</param> /// <param name="parent">The Parent Node of the given Node</param> /// <returns></returns> private ElementEvent GenerateEvents(RdfXmlParserContext context, XmlNode node, IRdfXmlEvent parent) { //Get the Base Uri String baseUri = String.Empty; if (parent is ElementEvent) { baseUri = ((ElementEvent)parent).BaseUri; } //Create an ElementEvent for the Node ElementEvent element = new ElementEvent(node.LocalName, node.Prefix, baseUri, node.OuterXml); //Set the initial Language from the Parent ElementEvent parentEl = (ElementEvent)parent; element.Language = parentEl.Language; #region Attribute Processing //Iterate over Attributes bool parseTypeLiteral = false; foreach (XmlAttribute attr in node.Attributes) { //Watch out for special attributes if (attr.Name == "xml:lang") { //Set Language element.Language = attr.Value; } else if (attr.Name == "xml:base") { //Set Base Uri if (RdfXmlSpecsHelper.IsAbsoluteURI(attr.Value)) { //Absolute Uri element.BaseUri = attr.Value; } else if (!element.BaseUri.Equals(String.Empty)) { //Relative Uri with a Base Uri to resolve against //element.BaseUri += attr.Value; element.BaseUri = Tools.ResolveUri(attr.Value, element.BaseUri); } else { //Relative Uri with no Base Uri throw new RdfParseException("Cannot resolve a Relative Base URI since there is no in-scope Base URI"); } } else if (attr.Prefix == "xmlns") { //Register a Namespace String uri; if (attr.Value.StartsWith("http://")) { //Absolute Uri uri = attr.Value; } else if (!element.BaseUri.Equals(String.Empty)) { //Relative Uri with a Base Uri to resolve against //uri = element.BaseUri + attr.Value; uri = Tools.ResolveUri(attr.Value, element.BaseUri); } else { //Relative Uri with no Base Uri throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI"); } NamespaceAttributeEvent ns = new NamespaceAttributeEvent(attr.LocalName, uri, attr.OuterXml); element.NamespaceAttributes.Add(ns); } else if (attr.Prefix == String.Empty && attr.Name == "xmlns") { //Register a Default Namespace (Empty Prefix) String uri; if (attr.Value.StartsWith("http://")) { //Absolute Uri uri = attr.Value; } else if (!element.BaseUri.Equals(String.Empty)) { //Relative Uri with a Base Uri to resolve against //uri = element.BaseUri + attr.Value; uri = Tools.ResolveUri(attr.Value, element.BaseUri); } else { //Relative Uri with no Base Uri throw new RdfParseException("Cannot resolve a Relative Namespace URI since there is no in-scope Base URI"); } NamespaceAttributeEvent ns = new NamespaceAttributeEvent(String.Empty, uri, attr.OuterXml); element.NamespaceAttributes.Add(ns); } else if (attr.Prefix == "xml" || (attr.Prefix == String.Empty && attr.LocalName.StartsWith("xml"))) { //Ignore other Reserved XML Names } else if (attr.Name == "rdf:parseType" && attr.Value == "Literal") { //Literal Parse Type parseTypeLiteral = true; //Create the Attribute AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml); element.Attributes.Add(attrEvent); //Set ParseType property correctly element.ParseType = RdfXmlParseType.Literal; } else if (attr.Name == "rdf:parseType") { //Some other Parse Type //Create the Attribute AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml); element.Attributes.Add(attrEvent); //Set the ParseType property correctly if (attr.Value == "Resource") { element.ParseType = RdfXmlParseType.Resource; } else if (attr.Value == "Collection") { element.ParseType = RdfXmlParseType.Collection; } else { //Have to assume Literal element.ParseType = RdfXmlParseType.Literal; parseTypeLiteral = true; //Replace the Parse Type attribute with one saying it is Literal element.Attributes.Remove(attrEvent); attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, "Literal", attr.OuterXml); } } else { //Normal Attribute which we generate an Event from AttributeEvent attrEvent = new AttributeEvent(attr.LocalName, attr.Prefix, attr.Value, attr.OuterXml); element.Attributes.Add(attrEvent); } } //Validate generated Attributes for Namespace Confusion and URIRef encoding foreach (AttributeEvent a in element.Attributes) { //Namespace Confusion should only apply to Attributes without a Namespace specified if (a.Namespace.Equals(String.Empty)) { if (RdfXmlSpecsHelper.IsAmbigiousAttributeName(a.LocalName)) { //Can't use any of the RDF terms that mandate the rdf: prefix without it throw ParserHelper.Error("An Attribute with an ambigious name '" + a.LocalName + "' was encountered. The following attribute names MUST have the rdf: prefix - about, aboutEach, ID, bagID, type, resource, parseType", element); } } //URIRef encoding check if (!RdfXmlSpecsHelper.IsValidUriRefEncoding(a.Value)) { throw ParserHelper.Error("An Attribute with an incorrectly encoded URIRef was encountered, URIRef's must be encoded in Unicode Normal Form C", a); } } #endregion //Don't proceed if Literal Parse Type is on if (parseTypeLiteral) { //Generate an XMLLiteral from its Inner Xml (if any) TypedLiteralEvent lit = new TypedLiteralEvent(node.InnerXml.Normalize(), RdfSpecsHelper.RdfXmlLiteral, node.InnerXml); element.Children.Add(lit); return element; } //Are there Child Nodes? if (node.HasChildNodes) { //Take different actions depending on the Number and Type of Child Nodes if (node.ChildNodes.Count > 1) { //Multiple Child Nodes //Iterate over Child Nodes foreach (XmlNode child in node.ChildNodes) { //Ignore Irrelevant Node Types if (this.IsIgnorableNode(child)) { continue; } //Generate an Event for the Child Node ElementEvent childEvent = this.GenerateEvents(context, child, element); element.Children.Add(childEvent); } } else if (node.ChildNodes[0].NodeType == XmlNodeType.Text) { //Single Child which is a Text Node //Generate a Text Event TextEvent text = new TextEvent(node.InnerText.Normalize(), node.OuterXml); element.Children.Add(text); } else if (node.ChildNodes[0].NodeType == XmlNodeType.CDATA) { //Single Child which is a CData Node TextEvent text = new TextEvent(node.InnerXml.Normalize(), node.OuterXml); element.Children.Add(text); } else { //Single Child which is not a Text Node //Recurse on the single Child Node if (!this.IsIgnorableNode(node.ChildNodes[0])) { ElementEvent childEvent = this.GenerateEvents(context, node.ChildNodes[0], element); element.Children.Add(childEvent); } } } return element; }