Creación de sistemas de lectura XML personalizados
Los sistemas de lectura XML personalizados permiten a las aplicaciones extender las clases XmlReader o XmlTextReader, o bien definir sus sistemas de lectura personalizados propios.
Ejemplo de extensión de XmlTextReader
En el ejemplo siguiente se muestra cómo extender XmlTextReader para crear un sistema de lectura que convierta atributos en elementos. La función Read reemplazada proporciona la lógica necesaria para realizar el seguimiento del tipo de nodo actual y, si es un atributo, lo expone como un tipo de nodo de elemento mediante las propiedades XmlNodeType.Name y XmlNodeType.Value.
Option Explicit
Option Strict
Imports System
Imports System.IO
Imports System.Text
Imports System.Xml
Imports System.Xml.XPath
Public Class AttrToElementReader
Inherits XmlTextReader
Private _ReadAttributes As Boolean = False
Private _ReadAttributeValue As Boolean = False
Private _AttributeName As String = String.Empty
Private _NodeType As XmlNodeType = XmlNodeType.None
Public Sub New(fileName As String)
MyBase.New(fileName)
MyBase.WhitespaceHandling = WhitespaceHandling.None
' Intentionally Empty
End Sub
Public Overrides Function Read() As Boolean
If Not _ReadAttributes Then
Dim baseRead As Boolean = MyBase.Read()
_ReadAttributes = baseRead And XmlNodeType.Element = MyBase.NodeType And 0 < MyBase.AttributeCount
Return baseRead
End If
'Read attribues;
If _ReadAttributeValue Then
_ReadAttributeValue = MyBase.ReadAttributeValue()
If Not _ReadAttributeValue Then
' End of attribute.
' End element.
_NodeType = XmlNodeType.EndElement
Else
_NodeType = XmlNodeType.None
End If
Return True
End If
_ReadAttributes = MyBase.MoveToNextAttribute()
If _ReadAttributes Then
_ReadAttributeValue = True
_NodeType = XmlNodeType.Element
_AttributeName = MyBase.Name
Return True
Else
_ReadAttributeValue = False
_NodeType = XmlNodeType.None
_AttributeName = String.Empty
Return Read()
End If
End Function
Public Overrides ReadOnly Property NodeType() As XmlNodeType
Get
If XmlNodeType.None = _NodeType Then
Return MyBase.NodeType
End If
Return _NodeType
End Get
End Property
Public Overrides ReadOnly Property Value() As String
Get
If XmlNodeType.None = _NodeType Then
Return MyBase.Value
End If
Return String.Empty
End Get
End Property
Public Overrides ReadOnly Property Name() As String
Get
If XmlNodeType.None = _NodeType Then
Return MyBase.Name
End If
Return _AttributeName
End Get
End Property
End Class 'AttrToElementReader
[C#]
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;
public class AttrToElementReader: XmlTextReader {
private bool _ReadAttributes = false;
private bool _ReadAttributeValue = false;
private string _AttributeName = String.Empty;
private XmlNodeType _NodeType = XmlNodeType.None;
public AttrToElementReader(String fileName) : base(fileName) {
base.WhitespaceHandling = WhitespaceHandling.None;
// Intentionally Empty.
}
public override bool Read() {
if (!_ReadAttributes) {
bool baseRead = base.Read();
_ReadAttributes = (baseRead && XmlNodeType.Element == base.NodeType && 0 < base.AttributeCount);
return baseRead;
}
// Reading attribues;
if (_ReadAttributeValue) {
_ReadAttributeValue = base.ReadAttributeValue();
if (!_ReadAttributeValue) {
// End of attribute.
// End element.
_NodeType = XmlNodeType.EndElement;
}
else {
_NodeType = XmlNodeType.None;
}
return true;
}
_ReadAttributes = base.MoveToNextAttribute();
if (_ReadAttributes) {
_ReadAttributeValue = true;
_NodeType = XmlNodeType.Element;
_AttributeName = base.Name;
return true;
}
else {
_ReadAttributeValue = false;
_NodeType = XmlNodeType.None;
_AttributeName = String.Empty;
return Read();
}
}
public override XmlNodeType NodeType {
get {
if (XmlNodeType.None == _NodeType) {
return base.NodeType;
}
return _NodeType;
}
}
public override String Value {
get {
if (XmlNodeType.None == _NodeType) {
return base.Value;
}
return String.Empty;
}
}
public override String Name {
get {
if (XmlNodeType.None == _NodeType) {
return base.Name;
}
return _AttributeName;
}
}
}//AttrToElementReader
Encadenar XmlReader
En el ejemplo siguiente se muestra una clase de implementación, denominada XmlReaderReader, que se usa como clase para encadenar el sistema de lectura XmlReader con el fin de proporcionar un flujo de sistemas de lectura mediante la delegación de las llamadas. Esto resulta útil al crear sistemas de lectura que filtren entradas específicas y es una solución eficaz para realizar análisis concretos de XML.
Una clase derivada de esta clase XmlReaderReader puede aceptar cualquier XmlReader como entrada. En el ejemplo siguiente, la clase XmlCustomReader sobrecarga el método Read y omite los nodos de elemento price
pasados, con lo que los quita de la secuencia.
' This sample demonstrate the ability to chain XmlReaders together by
' implementing an XmlReaderReader class which aggregates any given
' XmlReader and then delegates the calls to it
Namespace Test
Public Class MyApp
Public Shared Sub Main()
Dim reader As New XmlTextReader("books.xml")
Dim customreader As New XmlCustomReader(reader)
customreader.ReadandWrite()
End Sub
Class XmlCustomReader
Inherits XmlReaderReader
Public Sub New(reader As XmlTextReader)
MyBase.New(reader)
End Sub
Public Overrides Function Read() As Boolean
Dim result As Boolean
result = MyBase.Read()
Select Case MyBase.NodeType
Case XmlNodeType.Element
If MyBase.Name.Equals("price") Then
MyBase.Skip()
End If
Case Else
End Select
Return result
End Function
Public Sub ReadandWrite()
' Read each node in the tree.
While Read()
Select Case NodeType
Case XmlNodeType.Element
Console.Write(("<" + Name))
While MoveToNextAttribute()
Console.Write((" " + Name + "='" + Value + "'"))
End While
Console.Write(">")
Case XmlNodeType.Text
Console.Write(Value)
Case XmlNodeType.CDATA
Console.Write(Value)
Case XmlNodeType.ProcessingInstruction
Console.Write(("<?" + Name + " " + Value + "?>"))
Case XmlNodeType.Comment
Console.Write(("<!--" + Value + "-->"))
Case XmlNodeType.Document
Console.Write("<?xml version='1.0'?>")
Case XmlNodeType.Whitespace
Console.Write(Value)
Case XmlNodeType.SignificantWhitespace
Console.Write(Value)
Case XmlNodeType.EndElement
Console.Write(("</" + Name + ">"))
End Select
End While
End Sub
End Class
Public Class XmlReaderReader
Inherits XmlTextReader
Private _Reader As XmlTextReader
Public Sub New(reader As XmlTextReader)
_Reader = reader
End Sub
' XmlReader methods and properties.
Public Overrides ReadOnly Property NodeType() As XmlNodeType
Get
Return _Reader.NodeType
End Get
End Property
Public Overrides ReadOnly Property Name() As [String]
Get
Return _Reader.Name
End Get
End Property
Public Overrides ReadOnly Property LocalName() As [String]
Get
Return _Reader.LocalName
End Get
End Property
Public Overrides ReadOnly Property NamespaceURI() As [String]
Get
Return _Reader.NamespaceURI
End Get
End Property
Public Overrides ReadOnly Property Prefix() As [String]
Get
Return _Reader.Prefix
End Get
End Property
Public Overrides ReadOnly Property HasValue() As Boolean
Get
Return _Reader.HasValue
End Get
End Property
Public Overrides ReadOnly Property Value() As String
Get
Return _Reader.Value
End Get
End Property
Public Overrides ReadOnly Property Depth() As Integer
Get
Return _Reader.Depth
End Get
End Property
Public Overrides ReadOnly Property BaseURI() As String
Get
Return _Reader.BaseURI
End Get
End Property
Public Overrides ReadOnly Property IsEmptyElement() As Boolean
Get
Return _Reader.IsEmptyElement
End Get
End Property
Public Overrides ReadOnly Property IsDefault() As Boolean
Get
Return _Reader.IsDefault
End Get
End Property
Public Overrides ReadOnly Property QuoteChar() As Char
Get
Return _Reader.QuoteChar
End Get
End Property
Public Overrides ReadOnly Property XmlSpace() As XmlSpace
Get
Return _Reader.XmlSpace
End Get
End Property
Public Overrides ReadOnly Property XmlLang() As String
Get
Return _Reader.XmlLang
End Get
End Property
Public Overrides ReadOnly Property AttributeCount() As Integer
Get
Return _Reader.AttributeCount
End Get
End Property
Overloads Public Overrides Function GetAttribute(name As String) As String
Return _Reader.GetAttribute(name)
End Function
Overloads Public Overrides Function GetAttribute(name As String, namespaceURI As String) As String
Return _Reader.GetAttribute(name, namespaceURI)
End Function
Overloads Public Overrides Function GetAttribute(i As Integer) As String
Return _Reader.GetAttribute(i)
End Function
Default Public Overrides Overloads ReadOnly Property Item(i As Integer) As String
Get
Return _Reader(i)
End Get
End Property
Default Public Overrides Overloads ReadOnly Property Item(name As String) As String
Get
Return _Reader(name)
End Get
End Property
Default Public Overrides Overloads ReadOnly Property Item(name As String, namespaceURI As String) As String
Get
Return _Reader(name, namespaceURI)
End Get
End Property
Overloads Public Overrides Function MoveToAttribute(name As String) As Boolean
Return _Reader.MoveToAttribute(name)
End Function
Overloads Public Overrides Function MoveToAttribute(name As String, ns As String) As Boolean
Return _Reader.MoveToAttribute(name, ns)
End Function
Overloads Public Overrides Sub MoveToAttribute(i As Integer)
_Reader.MoveToAttribute(i)
End Sub
Public Overrides Function MoveToFirstAttribute() As Boolean
Return _Reader.MoveToFirstAttribute()
End Function
Public Overrides Function MoveToNextAttribute() As Boolean
Return _Reader.MoveToNextAttribute()
End Function
Public Overrides Function MoveToElement() As Boolean
Return _Reader.MoveToElement()
End Function
' This is the only place that needs to be changed.
Public Overrides Function Read() As Boolean
Return _Reader.Read()
End Function
Public Overrides ReadOnly Property EOF() As Boolean
Get
Return _Reader.EOF
End Get
End Property
Public Overrides Overloads Sub Close()
_Reader.Close()
End Sub
Public Overrides ReadOnly Property ReadState() As ReadState
Get
Return _Reader.ReadState
End Get
End Property
Public Overrides Function ReadString() As String
Return _Reader.ReadString()
End Function
Public Overrides Function ReadInnerXml() As String
Return _Reader.ReadInnerXml()
End Function
Public Overrides Function ReadOuterXml() As String
Return _Reader.ReadOuterXml()
End Function
Public Overrides ReadOnly Property NameTable() As XmlNameTable
Get
Return _Reader.NameTable
End Get
End Property
Public Overrides Function LookupNamespace(prefix As String) As String
Return _Reader.LookupNamespace(prefix)
End Function
Public Overrides Overloads Sub ResolveEntity()
_Reader.ResolveEntity()
End Sub
Public Overrides Function ReadAttributeValue() As Boolean
Return _Reader.ReadAttributeValue()
End Function
End Class
End Class
End Namespace
[C#]
using System;
using System.Xml;
// This sample demonstrate the ability to chain XmlReaders together by
// implementing an XmlReaderReader class which aggregates any given
// XmlReader and then delegates the calls to it.
namespace Test
{
public class MyApp
{
public static void Main()
{
XmlTextReader reader = new XmlTextReader("books.xml");
XmlChainingReader customreader = new XmlChainingReader(reader);
customreader.ReadandWrite();
}
class XmlChainingReader : XmlReaderReader
{
public XmlChainingReader (XmlReader reader) : base (reader)
{}
public override bool Read ()
{
bool result;
result = base.Read();
switch (base.NodeType)
{
case XmlNodeType.Element:
if (base.Name.Equals("price"))
base.Skip();
break;
default:
break;
}
return result;
}
public void ReadandWrite()
{
// Read each node in the tree.
while (Read())
{
switch (NodeType)
{
case XmlNodeType.Element:
Console.Write("<" + Name);
while (MoveToNextAttribute())
Console.Write(" " + Name + "='" + Value + "'");
Console.Write(">");
break;
case XmlNodeType.Text:
Console.Write(Value);
break;
case XmlNodeType.CDATA:
Console.Write(Value);
break;
case XmlNodeType.ProcessingInstruction:
Console.Write("<?" + Name + " " + Value + "?>");
break;
case XmlNodeType.Comment:
Console.Write("<!--" + Value + "-->");
break;
case XmlNodeType.Document:
Console.Write("<?xml version='1.0'?>");
break;
case XmlNodeType.Whitespace:
Console.Write(Value);
break;
case XmlNodeType.SignificantWhitespace:
Console.Write(Value);
break;
case XmlNodeType.EndElement:
Console.Write("</" + Name + ">");
break;
}
}
}
}
public class XmlReaderReader : XmlReader
{
XmlReader _Reader;
public XmlReaderReader (XmlReader reader )
{
_Reader = reader;
}
// XmlReader methods and properties.
public override XmlNodeType NodeType
{
get { return _Reader.NodeType; }
}
public override String Name
{
get { return _Reader.Name; }
}
public override String LocalName
{
get { return _Reader.LocalName; }
}
public override String NamespaceURI
{
get { return _Reader.NamespaceURI; }
}
public override String Prefix
{
get { return _Reader.Prefix; }
}
public override bool HasValue
{
get { return _Reader.HasValue; }
}
public override string Value
{
get { return _Reader.Value; }
}
public override int Depth
{
get { return _Reader.Depth; }
}
public override string BaseURI
{
get { return _Reader.BaseURI; }
}
public override bool IsEmptyElement
{
get { return _Reader.IsEmptyElement; }
}
public override bool IsDefault
{
get { return _Reader.IsDefault; }
}
public override char QuoteChar
{
get { return _Reader.QuoteChar; }
}
public override XmlSpace XmlSpace
{
get { return _Reader.XmlSpace; }
}
public override string XmlLang
{
get { return _Reader.XmlLang; }
}
public override int AttributeCount
{
get { return _Reader.AttributeCount; }
}
public override string GetAttribute(string name)
{
return _Reader.GetAttribute( name );
}
public override string GetAttribute(string name, string namespaceURI)
{
return _Reader.GetAttribute( name, namespaceURI );
}
public override string GetAttribute(int i)
{
return _Reader.GetAttribute( i );
}
public override string this [ int i ]
{
get { return _Reader[ i ]; }
}
public override string this [ string name ]
{
get { return _Reader[ name ]; }
}
public override string this [ string name,string namespaceURI ]
{
get { return _Reader[ name, namespaceURI ]; }
}
public override bool MoveToAttribute(string name)
{
return _Reader.MoveToAttribute( name );
}
public override bool MoveToAttribute(string name, string ns)
{
return _Reader.MoveToAttribute( name, ns );
}
public override void MoveToAttribute(int i)
{
_Reader.MoveToAttribute( i );
}
public override bool MoveToFirstAttribute()
{
return _Reader.MoveToFirstAttribute();
}
public override bool MoveToNextAttribute()
{
return _Reader.MoveToNextAttribute();
}
public override bool MoveToElement()
{
return _Reader.MoveToElement();
}
//
// This is the only place that needs to be changed.
//
public override bool Read()
{
return _Reader.Read();
}
public override bool EOF
{
get { return _Reader.EOF; }
}
public override void Close()
{
_Reader.Close();
}
public override ReadState ReadState
{
get { return _Reader.ReadState; }
}
public override string ReadString()
{
return _Reader.ReadString();
}
public override string ReadInnerXml()
{
return _Reader.ReadInnerXml();
}
public override string ReadOuterXml()
{
return _Reader.ReadOuterXml();
}
public override XmlNameTable NameTable
{
get { return _Reader.NameTable; }
}
public override string LookupNamespace(string prefix)
{
return _Reader.LookupNamespace( prefix );
}
public override void ResolveEntity()
{
_Reader.ResolveEntity();
}
public override bool ReadAttributeValue()
{
return _Reader.ReadAttributeValue();
}
}
}
}
Vea también
Leer XML con XmlReader | Leer datos XML con XmlTextReader | Leer árboles de nodos con XmlNodeReader | Validar XML con XmlValidatingReader | XmlReader (Clase) | XmlReader (Miembros) | XmlNodeReader (Clase) | XmlNodeReader (Miembros) | XmlTextReader (Clase) | XmlTextReader (Miembros) | XmlValidatingReader (Clase) | XmlValidatingReader