Figure 1
Figure 1 The System.Xml Namespace Architecture
Figure 5 Console Output
[XmlDeclaration]
[Whitespace]
[Comment]
[Whitespace]
[ProcessingInstruction]
[Whitespace]
[Element]
[Whitespace]
[Element]
[Text]
[EndTag]
[Whitespace]
[Element]
[Text]
[EndTag]
[Whitespace]
[EndTag]
Figure 6 Reading or Serializing Documents
using System;
using System.Xml;
// rest of class omitted for clarity
public void ReadDocumentAndSerialize(XmlReader reader)
{
// read each node in the tree
while (reader.Read())
{
// serialize node out to console according to XML 1.0 + Names
switch (reader.NodeType)
{
case XmlNodeType.Element:
Console.Write("<" + reader.Name);
while (reader.MoveToNextAttribute())
Console.Write(" " + reader.Name + "='" + reader.Value + "'");
Console.Write(">");
break;
case XmlNodeType.Text:
Console.Write(reader.Value);
break;
case XmlNodeType.CDATA:
Console.Write(reader.Value);
break;
case XmlNodeType.ProcessingInstruction:
Console.Write("<?" + reader.Name + " " + reader.Value + "?>");
break;
case XmlNodeType.Comment:
Console.Write("<!--" + reader.Value + "-->");
break;
case XmlNodeType.Document:
Console.Write("<?xml version='1.0'?>");
break;
case XmlNodeType.Whitespace:
Console.Write(reader.Value);
break;
case XmlNodeType.SignificantWhitespace:
Console.Write(reader.Value);
break;
case XmlNodeType.EndTag:
Console.Write("</" + reader.Name + ">");
break;
}
}
}
Figure 7 XmlTextReader and Validation
// if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons
using System;
using System.Xml;
public class ValidateUtility
{
static bool m_error = false;
public static void Main(String[] args)
{
if (args.Length < 1)
{
Console.WriteLine("usage: validate filename [-dtd,
-schema, -none]");
return;
}
try
{
// create instance of XmlTextReader
XmlTextReader tr = new XmlTextReader(args[0]);
// specify what type of validation to perform
if (args.Length > 1)
{
if (args[1].Equals("-dtd"))
tr.Validation = Validation.DTD;
else if (args[1].Equals("-schema"))
tr.Validation = Validation.Schema;
else if (args[1].Equals("-none"))
tr.Validation = Validation.None;
else
tr.Validation = Validation.Auto;
}
// register event callback (for validation errors)
tr.ValidationEventHandler += new
ValidationEventHandler(ValidationCallback);
// read through entire document
while (tr.Read()) ;
if (!m_error)
Console.WriteLine("success: document is valid");
}
catch(XmlException e)
{
Console.WriteLine("###error: " + e.Message);
}
return;
}
public static void ValidationCallback (Object obj,
ValidationEventArgs args)
{
m_error = true;
Console.Write("\r\n\t###validation error: " + args.Message);
}
}
Figure 8 Configuring XmlTextReader
using System;
using System.Xml;
public static void Main(String[] args)
{
try
{
// file name passed in args[0]
XmlTextReader tr = new XmlTextReader(args[0]);
// specify custom entity resolver
tr.XmlResolver = new MyResolver();
// don't report whitespace
tr.WhitespaceHandling = WhitespaceHandling.None;
// optimize entity expansion
// must call ResolveEntity to expand
tr.EntityHandling = EntityHandling.AllEntityNodes;
// use dtd/schema for entity expansion & default attributes
// but don't validate
tr.Validation = Validation.Auto;
// read through the document
while (tr.Read())
{
// process nodes here
}
}
catch(XmlException e)
{
Console.WriteLine("###error: " + e.Message);
}
}
Figure 9 Custom XmlReader for Processing XIncludes
// if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons
using System;
using System.Xml;
public class XincUtility
{
public static void Main(String[] args)
{
try
{
// create an instance of our custom XmlReader (XincReader) and
// configure
XincReader r = new XincReader(args[0]);
r.WhitespaceHandling = WhitespaceHandling.None;
XmlTextWriter tw = new XmlTextWriter(Console.Out);
tw.Formatting = Formatting.Indented;
tw.WriteStartDocument();
while (r.Read())
SerializeNode(r, tw);
tw.WriteEndDocument();
}
catch(XmlException e)
{
Console.WriteLine("###error: " + e.Message);
}
return;
}
public static void SerializeNode(XmlReader reader, XmlWriter w)
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
w.WriteStartElement(reader.Prefix, reader.LocalName,
reader.NamespaceURI);
while (reader.MoveToNextAttribute())
{
w.WriteStartAttribute(reader.Prefix, reader.LocalName,
reader.NamespaceURI);
w.WriteString(reader.Value);
w.WriteEndAttribute();
}
break;
case XmlNodeType.Text:
w.WriteString(reader.Value);
break;
case XmlNodeType.CDATA:
w.WriteCData(reader.Value);
break;
case XmlNodeType.ProcessingInstruction:
w.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
w.WriteComment(reader.Value);
break;
case XmlNodeType.EndTag:
w.WriteEndElement();
break;
}
}
}
public class XincReader : XmlTextReader
{
// nested reader for processing XInclude elements
XincReader m_NestedReader;
public XincReader(String sURI) : base(sURI) {m_NestedReader=null;}
// custom implementation of Read: if a nested reader exists, delegate
// otherwise, Read the next node and check for xinc:href
// if one exists create another nested reader and continue
public override bool Read()
{
bool bMore;
String strHref = null;
// if nested reader exists, delegate
if (m_NestedReader != null)
{
bMore = m_NestedReader.Read();
// if done with nested reader, free resources & reset state
if (!bMore)
{
m_NestedReader.Close();
m_NestedReader = null;
return base.Read();
}
else return true;
}
else
{
// read the next node and check for xinc:href
bMore = base.Read();
strHref = base.GetAttribute("href",
"https://www.w3.org/1999/XML/xinclude");
// if found, create a new nested reader and move to the first node
if (strHref != null)
{
m_NestedReader = new XincReader(strHref);
m_NestedReader.Read();
// move past XmlDeclaration if present
if (m_NestedReader.NodeType == XmlNodeType.XmlDeclaration)
m_NestedReader.Read();
return true;
}
else
return bMore;
}
}
// override all of XmlTextReader's methods to delegate
// to nested reader if one exists
public string Name
{
override get
{
if (m_NestedReader != null)
return m_NestedReader.Name;
else
return base.Name;
}
}
public XmlNodeType NodeType
{
override get
{
if (m_NestedReader != null)
return m_NestedReader.NodeType;
else
return base.NodeType;
}
}
public string NamespaceURI
{
override get
{
if (m_NestedReader != null)
return m_NestedReader.NamespaceURI;
else
return base.NamespaceURI;
}
}
public string LocalName
{
override get
{
if (m_NestedReader != null)
return m_NestedReader.LocalName;
else
return base.LocalName;
}
}
public string Prefix
{
override get
{
if (m_NestedReader != null)
return m_NestedReader.Prefix;
else
return base.Prefix;
}
}
public string Value
{
override get
{
if (m_NestedReader != null)
return m_NestedReader.Value;
else
return base.Value;
}
}
public int AttributeCount
{
override get
{
if (m_NestedReader != null)
return m_NestedReader.AttributeCount;
else
return base.AttributeCount;
}
}
public override bool MoveToNextAttribute()
{
if (m_NestedReader != null)
return m_NestedReader.MoveToNextAttribute();
else
return base.MoveToNextAttribute();
}
// others excluded for simplicity...
}
Figure 10 .NET DOM Class Hierarchy
Figure 11 Generating a Document using the DOM
using System;
using System.Xml;
public class GenerateDocument
{
public static void Main(String[] args)
{
// instantiate the document
XmlDocument doc = new XmlDocument();
XmlNode node;
// create a comment/pi and append
node = doc.CreateComment("sample person document");
doc.AppendChild(node);
node = doc.CreateProcessingInstruction("hack", "on person");
doc.AppendChild(node);
// create the person element within the 'urn:person' namespace
node = doc.CreateElement("p", "person", "urn:person");
doc.AppendChild(node);
// create the name/age elements in no namespace
node = doc.CreateElement("name");
node.InnerText = "joebob";
doc.DocumentElement.AppendChild(node);
node = doc.CreateElement("age");
node.InnerText = "28";
doc.DocumentElement.AppendChild(node);
// serialize the document to the console
XmlTextWriter tw = new XmlTextWriter(Console.Out);
tw.Formatting = Formatting.Indented;
doc.Save(tw);
}
}
Figure 12 XPath Console Utility
// if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons
using System;
using System.Xml;
class XPathUtility
{
public static void Main(String[] args)
{
if (args.Length < 2)
{
System.Console.WriteLine
("usage: xpath.exe filename xpath-expr [-eval]");
}
else
{
try
{
// load XML document w/input file
XmlDocument doc = new XmlDocument();
doc.Load(args[0]);
// wrap with an XmlNavigaor
DocumentNavigator nav = new DocumentNavigator(doc);
// if -eval, call evaluate and return the result
if (args.Length == 3 && args[2].Equals("-eval"))
{
Console.WriteLine(nav.Evaluate(args[1]));
return;
}
// otherwise call Select
nav.Select(args[1]);
// create an XmlTextWriter to the console
XmlTextWriter xw = new XmlTextWriter(Console.Out);
xw.Formatting = Formatting.Indented;
// create a new document for the selected nodes
XmlDocument docoutput = new XmlDocument();
XmlElement e = docoutput.CreateElement("selection");
docoutput.AppendChild(e);
DocumentNavigator navoutput = new DocumentNavigator(docoutput);
navoutput.MoveToDocumentElement();
// copy selected nodes to output document
navoutput.CopySelected(TreePosition.FirstChild, nav);
// serialize to console
docoutput.Save(xw);
}
catch(Exception e)
{
System.Console.WriteLine("###error: " + e.Message);
}
}
}
}
Figure 13 Transforming a Document with XslTransform
// if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons
using System;
using System.Xml;
using System.Xml.Xsl;
public class TransformationUtility
{
public static void transformDocument(String strXML,
String strXSLT, XmlWriter xw)
{
try
{
// load the source document (to be transformed)
XmlDocument docSource = new XmlDocument();
docSource.Load(strXML);
// wrap it with an XmlNavigator
DocumentNavigator navSource = new DocumentNavigator(docSource);
// create the XslTransform object
XslTransform tr = new XslTransform();
// load it with the stylesheet
tr.Load(strXSLT);
// call transform - output streamed to console
tr.Transform(navSource, null, xw);
}
catch(XmlException e)
{
Console.WriteLine("###error: " + e.Message);
}
}
public static void Main(String[] args)
{
if (args.Length < 2)
{
Console.WriteLine("usage: xslt sourcedoc xsltdoc [outdoc]");
return;
}
if (args.Length == 3)
{
// create an XmlTextWriter to a file on disk
XmlTextWriter tw = new XmlTextWriter(args[2], null);
transformDocument(args[0], args[1], tw);
return;
}
// otherwise send output to console
transformDocument(args[0], args[1], new XmlTextWriter(Console.Out));
}
}