Example - Youssef Bou Issa

clutteredreverandData Management

Oct 31, 2013 (3 years and 5 months ago)

571 views


1






Projet de programmation avancée

DGL 7432


Samir Saad







2


Chapter 1
: XML.NET

1
-

Introduction

I
n this
course we will
cover
the following

topics
:




Navigating, reading and writing XML documents by using the
System.xml namespace and the classes XmlDocument,

XmlReader, XmlWriter and XpathNavigator.



Validating XML
by

applying Schemas



Transforming XML by

applying XSLT transformation



XML and
ADO.NET



XML serialization


Topics at a glance

not included in this course
:




XML and the .NET Framework



Using XML with Linq



XML and WCF


2
-

Introducing xml and the .NET Framework

a.

What is XML

XML

stands for

eX
t
ensible Markup Language

and is a
markup language used to desrribe data.

It offers a standardized way to represent textual data.

The XML data doesn't perform anything on its own;
to process that data,
you need to use a piece of
software called a

parser
. unlike Hypertext Markup
Language (HTML), which focuses on how to present
data, XML focuses on how to represent data. XML
consists o
f user
-

defined tags, which means you are
free to define and use your own tags in an XML
document.

The following illustrates an
example:


<?xml version=”1.0”>

<customers>


3




<customer id=”id1”>



<name>n1</name>



<phone>09876534</phone>



<
/customer>


<customer id=”id2”>



<name>n2</name>



<phone>08876534</phone>



</customer>

</customers>


b.

Benefits of XML




XML is a standard: integrating cross
-
platform
application
s

is now easy
. For example a VB6 application
can now share data w
ith a JAVA application running on
UNIX



XML is self
-
describing



XML is extensible



Can be processed easily tha
n

.CSV files



Can be used to create specialized vocabularies like XML
Schemas, WML,

WAP and SOAP.


c.

XML Parsers


The software that processes XML documents is called Parser,
and they
allow you
parse for syntax errors,
read, write and
manipulate XML documents
. They can be classified in two
categories depending on how they can process XML data:




DOM (Document Object Mod
el)
parsers.

(XmlDocument
class)



SAX parsers.

(Simple API for XML)

(
e.g

:
XmlTextReader,
XmlTextWriter)


4


DOM
parsers
process XML as a tree structure
, they are
Read/Write, allow random access to any node, but, they need
to load the entire XML document in me
mory.


SAX parsers
do not read the entire XML document into
memory at once
. They scan the document sequentially and
raise events. We can handle these events to read the
document. SA
X parsers are read
-
only parsers and they can be
used to optimize memory
allocation.


Note:


.NET3.0 introduced LINK (Language Integrated Query)

that offers a new way to read and write XML documents.


d.

XSLT

(Extensible Stylesheet Language
Transformations)


XML Solves the problem of data representation and exchange.
However when
we need to convert
this XML data into another
XML data or into a new format (e.g. HTML) understood by the
other application, we need to use XSLT.


e.

XPATH


It

consists of various XPATH expressions

and functions that we
can use to look for and select elements and attributes
matching certain criteria.


f.

The .NET FRAMEWORK


It is a platform for building Windows and Web applications,
components and services by using a variety of languages.
Figure A.1 de
pict the .NET Stack


5



Fig. 1


The CLR

is the heart of the .NET Framework
. It provides the
executing environment to all the .Net applications, so in order
to run any .Net application the CLR must be installed. The CLR
does many things for your application:

memory and thread
management, security checking,…

The base class library

provides classes to perform everything
the application needs: I/O, database access, XML
manipulation, web and socket programming



g.

Assemblies and namespaces


The core
-
XML related classes from the base class library are
physically found in an assembly called System.Xml.dll.

Following are some important XML namespaces:




System.Xml:

XmlDocument, XmlTextReader,
XmlTextWriter, XmlNode, XmlElement, XmlAttribute,
Xm
lText…



System.Xml.Schema:

XmlSchema, XmlSchemaElement,
XmlSchemaComplexType…



System.Xml.Xpath:

XpathDocument, XpathExpression,
XpathNavigator, XpathNodeIterator…


6




System.Xml.Xsl:
XslCompiledTransform, XslTransform,
XslSettings…



System.Xml.Serialization:
XmlSerializer,
XmlAttributeAttribute, XmlRootAttribute,
XmlTextAttribute…



System.Xml.Linq:
X
D
ocument, X
E
lement,
XNode,
XText…


NOTE

: The Document Object Model


It has
its origin

in the
World Wide Web Consortium

(W3C) and
it is a standard to represent the content and model of
documents (HTML, XML, CSS, XML Validation handlers,..)
across all programming language and tools.

The DOM interface
supply a complete in
-
memory tree representation of the XML
document. So in

a typical XML Document we might get a
structure that looks like:





7


Because of this model, all DOM structures can be treated
either as their generic type,
Node
, or as their specific
type(Element, attribute, tesxt,..). many of the navigation
methods that
we will explore, are on the basic of Node
interface, so we can walk up and down the tree without
worrying about the specific structure type.

DOM defines its
own list structures like nodelists rather than .net collections.
The following figure shows a simpl
e UML
-
style model for DOM
core interfaces and classes.






8


3
-

Manipulating XMLDocuments by Using DOM


In this paragraph we will cover the following topics:




System.Xml namespace classes related to DOM



Knowing when to use DOM



Reading an XML Document by using
DOM



Writing XML Documents by using DOM


a.

Using the DOM Parser


At the heart of DOM manipulation we can find the
class
XmlDocument
.

It loads the XML document and builds its tree
representation. DOM is best suited in the following scenarios:




You want a read/
write access to the XML Document



Random access



Small document size


b.

Opening an existing XML document for parsing


The XmlDocument class allows you to open XML documents in
three common ways:


1.

Specify the path or the UR
I

of the XML file
:


string

filepath =
"C:
\
\
...
\
\
...
\
\
catalog.xml”;

XmlDocument

doc

=
new

XmlDocument
();

doc
.Load(filepath);


2.

Use a stream like FileStream that contains the XML Data
:


string

filepath =
"C:
\
\
...
\
\
...
\
\
catalog.xml”;


9


FileStream

fs =
new

FileStream
(filepath,
FileMode
.Open);

XmlDocument

doc

=
new

XmlDocument
();

doc
.Load(fs);
fs.Close();


3.

By using an XmlTextReader
: as we will see later


4.

A string in memory that contains the XML Data

string

str

=
"<book genre='g1' isbn='11'>"

+


"<title>tl1</title>"

+


"
</book>"

XmlDocument

doc

=
new

XmlDocument
();

doc
.Load
Xml
(
str
);


Practice 1


1
-

Create a windows application

2
-

Create an XML file that contains the following:


<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<
catalog
>





<
supplier

name
=
"
n1
"

uid
=
"
id1
"

pw
=
"
pw1
"

/>





<
batch

batch_type
=
"
cat_new
"
>






<
product

prod_code
=
"
c1
"

prod_type
=
"
t1
"
>







<
desc
>
desc1
</
desc
>







<
saleinfo

saleprice
=
"
10.3
"
></
saleinfo
>







<
supplier

id
=
"
s1
"
>
s1
</
supplier
>







<
supplier

id
=
"
s2
"
>
s2
</
supplier
>






</
product
>






<
product

prod_code
=
"
c11
"

prod_type
=
"
t11
"
>







<
desc
>
desc10
</
desc
>







<
saleinfo

saleprice
=
"
10.3
"
></
saleinfo
>







<
supplier

id
=
"
s4
"
>
s4
</
supplier
>







<
supplier

id
=
"
s5
"
>
s5
</
supplier
>






</
product
>





</
batch
>





<
batch

batch_type
=
"
cat_upd
"
>






<
product

prod_code
=
"
c2
"

prod_type
=
"
t1
"
>







<
desc
>
desc11
</
desc
>







<
saleinfo

saleprice
=
"
10.3
"
></
saleinfo
>







<
supplier

id
=
"
s11
"
>
s11
</
supplier
>







<
supplier

id
=
"
s2
"
>
s2
</
supplier
>






</
product
>





</
batch
>





<
batch

batch_type
=
"
cat_del
"
>






<
product

prod_code
=
"
c3
"

prod_type
=
"
t1
"
/>





</
batch
>

</
catalog
>


10


3
-

Write the application that loads the XmlDocument as
described in the following image



c.

Navigating Through an XML Document


An XML Document consists of one or more nodes, and nodes
can be nested
inside other nodes. Such nested nodes are
called child nodes.

The
XmlNode

node has a collection called
ChildNodes

that
contains a list of child nodes of the current node. The XmlNode
is the base class of most of the DOM classes. Further, this class
has
mor
e
properties such
ParentNode
,
FirstChild
,
LastChild
,
NextSibling
,
PreviousSibling
,
HasChildNodes
,
Attributes


that
allow you to navigate to the corresponding node
.


Example


By using the previous XML document we can write the
following:


//get the root: <
catalog>

XmlNode

root = doc.DocumentElement;

//will print out n1

label2.Text = root.FirstChild.Attributes[0].Value;

label2.Text = root.ChildNodes[0].Attributes[0].Value;

//Get the batch_type ATTRIBUTE value (cat_new) of the batch
//element



11


label2.Text =
root
.ChildNodes[1].Attributes[0].Value;

//// retreive desc1 (2 methods)

label2.Text =
root
.ChildNodes[1].ChildNodes[0].ChildNodes[0].FirstChild.V
alue;


label2.Text=
root
.ChildNodes[1].ChildNodes[0].ChildNodes[0].
InnerText;


//to
ref
er
the node saleinfo

XmlNode

x1 =
root
.ChildNodes[1].ChildNodes[0].ChildNodes[1];




if

(x1.InnerText != "")

//or



if

(x1.Name=="saleinfo")

//or


if

(x1.NodeType=="Element")





{


label2.Text = x1.FirstChild.Value;




label2.Text = x1.InnerText;




}


else




{




if

(x1.Attributes.Count != 0)




{


Label2.Text = x1.Attributes
[0].Value.ToString();




}


else





{




label2.Text =
"vide"
;


}


}





We note that
doc.ChildeNodes.Count

is equal to two

nodes.
These nodes are:

<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<
catalog
>



Practice 2

1
-

Create the windows application that load
s

the
employees.xml file into a TreeView as depicted in the
following Figure:



12



We note that ID is an attribute


Solution


d.

Lo
o
king For Specific Elements and Node


Often we are not interested in the entire XML Document
loaded in memory but part of it. This requires us to search for
a specific element or node for further processing. There are
several methods used to
search the XML Document.




Retrieving specific
elements

using the
GetElement
s
ByTagName() method

(Ret
u
rns an
XmlNodeList)



Retrieving specific
elements

using the GetElementById()
method
. (Returns an XmlElement)



Selecting specific
nodes

using the SelectNodes()

method



Selecting a single specific
node

using the
SelectSingleNode() method

(Returns XmlNode)



13


a
-

GetElement
s
ByTagName


This method accepts the name of the tag (
excluding <
and >
) and returns in a collection of XmlNode, all the
nodes matching that tag name.

By using the XML Document in Practice 1
we can write:


XmlNodeList

list;

list=
doc
.GetElementsByTagName(
"
product
"
);


foreach

(
XmlNode

x
in

list)



{





L
abel
1
.Text += x.Attributes[0].Value;


}

Practice 3






Solution




14


b
-

GetElementBy
Id


Often we want to search for a specific element
knowing its unique ID. This may not be performed by
the XmlDocument unless we bind the XML Document
to its DTD or Schema, where we have
defined the
unique ID.


Note

:

The DOM implementation must have
information which defines which attributes are of type
ID. Although attributes of type ID can be defined in
either XSD schemas or DTDs, this version of the
product only supports those defined
in DTDs.
Attributes with the name "ID" are not of type ID unless
so defined in the DTD.


Example


Given the following file.xml with its DTD:


<!DOCTYPE root [


<!ELEMENT root ANY>


<!ELEMENT Person ANY>


<!ELEMENT Customer ANY >


<!ELEMENT Team EMPTY
>


<!ATTLIST Person SSN ID #REQUIRED>
]>

<root>


<Person SSN='A111'>
Fred</Person>


<Person SSN='A222'>

Tom</Person>


<Customer>
C1
<
/
Customer>


<Customer>
C2
<
/
Customer>


<Team>
TM1
<
/
Team>

</root>


15


The code can be as follows
:


using System;

using

System.Xml;

public class Sample

{


public static void Main()


{


XmlDocument doc = new XmlDocument();


doc.Load("file.xml");


//Get the first element with an attribute of type ID

//
and value of A111.


//This displays the node
:


//

<
Person SSN="A111">
Fred</Person>
.


XmlElement elem = doc.GetElementById("A111");


Console.WriteLine( elem.OuterXml );


//Get the first element with an attribute of type ID
//
and value of A222.


//This displays Tom


elem = doc.GetElementById("A22
2");


Console.WriteLine( elem.ChildNodes[0].InnerText

);


}

}


Note

:

The XmlElement class inherits the XmlNode
class


c
-

SelectNodes


The XmlDocument has a method called SelectNodes
that accepts then XPath pattern to accomplish complex

16


search within the

DOM tree. It returns XmlNodeList
containing the matching nodes.


Example


To describe how the SelectNodes method works we
will develop a windows application that uses XPath to
filter the result. The follwing figure show the
application’s form






17


Solution




Where:


XmlNodeList list=null;


As we can see, the XPath filter will filter the employees
tag to only obtain the required
first name

or
last name.











18


The code of the Button will be:





d
-

SelectSingleNode

This method is very similar to
SelectNodes but it
return
s

the first matching XmlNode
.

As an example we can repeat the previous code and
replace the XmlNodeList list; by XmlNode node;




19


Practice 4


Considering the following XML file:

<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<
products
>


<
product
>



<
pid
>
1
</
pid
>



<
productname
>
fff
</
productname
>



<
price
>
45
</
price
>


</
product
>


<
product
>



<
pid
>
2
</
pid
>



<
productname
>
ggg
</
productname
>



<
price
>
56
</
price
>


</
product
>


<
product
>



<
pid
>
3
</
pid
>



<
productname
>
hhh
</
productname
>



<
price
>
12
</
price
>


</
product
>

</
products
>


By using
for

and foreach

loop
s
, write the code that
load
s

a ComboBox by the productname
.


e.

Modifying XML Documents

by using XmlDocument,

XmlNode

and/or
XmlElement

So far, we have seen how to read XML documents,
how to
navigate through them and how to search
them on the basis of the tag name.


Demo: Button 53 (
XmlLab_
Mod),

54(Del),

55(
Ins)


Practice 5


Given

following
employees.xml file, write a windows
application that allows the user to
navigate, add,

20


delete or modify nodes or attributes based on the

following Employees.
xml file:

<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<
employees
>


<
employee
employee
id=”1”
>



<
firstname
>
fn1
/
<
firstname
>



<
lastname
>
ln1
<
/
lastname
>



<
homephone
>
45
</
homephone
>



<
note
s
>n1</
note
s
>


</
employee
>


<
employee
employee
id=”
2

>



<
firstname
>fn
2
/<
firstname
>



<
lastname
>ln
2
</
lastname
>



<
homep
hone
>
4
6
</
homep
hone
>

<
note
s
>n2</
note
s
>


</
employee
>


<
employee
employee
id=”1”
>



<
firstname
>fn
3
/<
firstname
>



<
lastname
>ln
3
</
lastname
>



<
homephone
>
47
</
homephone
>

<
note
s
>n3</
note
s
>


</
employee
>

</
employees

>


The windows application form must be as follows:



Solution


21


f.

Dealing with Namespaces


XML Namespaces allow you to identify elements as
part of a single group (a namespace) by uniquely
qualifying element and attribute names used in an XML
document. Each name
space is identified by a URI
(Uniform Resource Identifier). This allows developer to
combine information from different data structures in
a single XML document without causing ambiguity and
confusion among element names.

For example, assume that you have
two XML
fragments, one related to employees and the other
related to customers. Further assume that both
fragments contain a tag called name.
The

problem is
that when you mix them together, you will obtain
ambiguity for the <name> tag.

XML namespaces
come

i
n handy in such situations.

the following example
shows the employees
_with_ns
.xml with its
namespace:

<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<
emp:
e
mployees xmlns:emp=”http//www.somedomain.com”
>


<
emp:employee employeeid=”1”
>



<
emp:firstname
>fn1/<
emp:firstname
>



<
emp:lastname
>ln1</
emp:lastname
>



<
emp:homephone
>
45
</
emp:homephone
>



<
emp:notes
>n1</
emp:notes
>


</
emp:employee
>


<
emp:employee employeeid=”2”
>



<
emp:firstname
>fn2/<
emp:firstname
>



<
emp:lastname
>ln2</
emp:lastname
>



<
emp:homephone
>
46
</
emp:homephone
>

<
emp:notes
>n2</
emp:notes
>


</
emp:employee
>


<
emp:employee employeeid=”1”
>



<
emp:firstname
>fn3/<
emp:firstname
>



<
emp:lastname
>ln3</
emp:lastname
>



<
emp:homephone
>
47
</
emp:homephone
>


22


<
emp:notes
>n3</
emp:notes
>


</
emp:employee
>

</
emp:
employees
>


The following code will extracts the namespace URI, the
prefix and the localname of the document as follows:






Homework
:
repea
t the paragraphs c, d and e by using the
employees_with_ns xml file


g.

Understanding Events of the XMLDocument class


Whenever you modify an XML document, the class raises pre
and post events that are lunched prior and after the actual
operation.



23




Each of the
e
vents receives an event argument parameter of
type XmlNodeChangedEventArgs that provides the following
propert
ies:




To understand these events we will modify and test the
previous application as follows:










24


1
-

Form Load



2
-

The event handlers



3
-

Test the module



25


4
-

Reading and Writing XML Documents


The previous chapter has introduced the DOM Tree parser
XmlDocument. In the following section we will explore XML reader
and writer classes.

a.

What
are

XML

Readers and Writers


DOM parsers are best suited to modifying XML documents that
are small. However with huge XML documents, DOM access
can pose problems in
terms of memory allocation and
performance. To resolve these issues the .NET Framework
provides
XmlReader and XmlWriter classes
. Although
XmlReader and SAX sound similar
,
they behave differently
. Any
SAX parser

essentially

raises events

as various parts of

the XML
document are encountred.
On the other hand
, the
XmlReader

class allows you to iterate through the document and access
the required content rather than raising events
. Thus
it

i
s more
flexible

from a development point of view, it does not load the
entire document in memory resulting in a
small memory
footprint, and, because it is read only, it is faster too
. Like
XmlReader is also the
XmlWriter
, it is a forward only model
and offers write
-
only functionality.

These classes are
abstract classes
. The System.Xml offers two
classes
XmlTextReader and XmlTextWriter that inherit

from
XmlReader and XmlWriter.

Additional reason to use these classes is when we do not need
to access various part of the document randomly.


b.

Reader classes




XmlTextReader


26




Xml
ValidatingReader: it can validate an XML document
against a DTD or XML schema



XmlNodeReader: allows you to read XML data from the
DOM tree. The constructor of XmlNodeReader takes a
parameter of type XmlNode that could be obtained as a
result of an XPath q
uery or directly fr
o
m a DOM
document.


c.

The XmlTextReader


a
-

Opening XML documents


1.

From a file path:


XmlTextReader

myrdr =
new

XmlTextReader

(filepath);

myrdr.Close();

2.

From a filestream:

myrdr.Close();


FileStream

str =
File
.OpenRead(filepath);


myrdr =
new

XmlTextReader
(str);

//processing...


str.Close();


myrdr.Close();


3.

From a
Memory
string:

MemoryStream

ms =
new

MemoryStream
();

byte
[] data =
ASCIIEncoding
.ASCII.GetBytes(textBox1.Text);


ms.Write(data, 0, data.Length);


myrdr =
new

XmlTextReader
(ms);


//processing


ms.Close();

myrdr.Close();




27


b
-

Reading Attributes, Elements and Values


The following examples demonstrate how we can use
the reader:


Example 1
: printing out all the nodes of the
catalog.xml file:

<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<
catalog
>


<
product

qt
=
"
2
"

cur
=
"
lbp
"
>



<
productid
>
id1
</
productid
>



<
productname
>
n1
</
productname
>



<
listprice
>
47.99
</
listprice
>


</
product
>

<!
--

comment
--
>


<
product

qt
=
"
20
"

cur
=
"
usds
"
>



<
productid
>
id2
</
productid
>



<
productname
>
n2
</
productname
>



<
listprice
>
20
</
listprice
>


</
product
>

</
catalog
>


string

filepath =
"C:
\
\
..
\
\
catalog1.xml"
;


XmlTextReader

myrdr =
new

XmlTextReader
(filepath);




//myrdr.WhitespaceHandling = WhitespaceHandling.None;


while

(myrdr.Read())


{

Console
.WriteLine(
"Type="

+ myrdr.NodeType.ToString()


+
" Name= "

+ myrdr.Name +
" Value= "

+


myrdr.Value);


}


myrdr.Close();







OUTPUT:


Type=XmlDeclaration Name=xml Value=



Type=Whitespace Name= Value=


Type=Element Name=catalog Value=


Type=Whitespace Name= Value=


Type=Element Name=
product
Value=


Type=Whitespace Name= Value=


Type=Element Name=productid Value=


Type=Text Name= Value= id1


Type=EndElement Name=productid Value=


Type=Whitespace
Name= Value=


28



Type=Element Name=productname Value=


Type=Text Name= Value= n1


Type=EndElement Name=productname Value=


Type=Whitespace Name= Value=


Type=Element Name=listprice Value=



Type=Text Name= Value= 47.99


Type=EndElement Name=listprice Value=


Type=Whitespace Name= Value=


Type=EndElement Name=product Value=


Type=Whitespace Name= Value=


Type=Element Name=produc
t Value=


Type=Whitespace Name= Value=


Type=Element Name=productid Value=


Type=Text Name= Value= id2


Type=EndElement Name=productid Value=


Type=Whitespace Name= Value=


Type=Element Name=productname Value=


Type=Text Name= Value= n2


Type=EndElement Name=productname Value=


Type=Whitespace Name= Value=


Type=Element Name=listprice Value=


Type=Text N
ame= Value= 20


Type=EndElement Name=listprice Value=


Type=Whitespace Name= Value=


Type=EndElement Name=product Value=


Type=Whitespace Name= Value=


Type=EndElement Name=catalog Value=


Type=Whitespace Name= Value=



Example
2
:
loadin
g

an xmldocument
from

a reader


string

filepath =
"C:
\
\
..
\
\
catalog1.xml"
;


XmlTextReader

myrdr =
new

XmlTextReader
(filepath);




myrdr.WhitespaceHandling =
WhitespaceHandling
.None;


XmlDocument

doc =
new

XmlDocument
();




doc.Load(myrdr);

MessageBox
.Show(doc.DocumentElement.ChildNodes[1].Att
ributes[0].Value);

XmlElement

el = doc.DocumentElement;
MessageBox
.Show(el.ChildNodes[1
].Attributes[0].Value)

Example
3
: Print out only the Text nodes


29




string

filepath =
"C:
\
\
..
\
\
catalog1.xml"
;


XmlTextReader

myrdr =
new

XmlTextReader
(filepath);




while

(myrdr.Read())


{




if

(myrdr.NodeType.ToString() ==
"Text"
)




{

//note that ther
e

is no Name only Type and
Values

Console
.Write(
"Type="

+
myrdr.NodeType.ToString() +
" Name= "

+
myrdr.Name +
" Value= "

+myrdr.Value);


}




}

myrdr.Close()


Example
4
: Print out only the Attribute nodes


string

filepath =
"C:
\
\
..
\
\
catalog1.xml"
;


XmlTextReader

myrdr =
new

XmlTextReader
(filepath);




while

(myrdr.Read())


{





if

(myrdr.HasAttributes)


{

for

(
int

i = 0; i <= myrdr.AttributeCount
-

1;

i++)


{





myrdr.MoveToAttribute(i);

Console
.Write(
"Type="

+
myrdr.NodeType.ToString() +

" Name= "

+ myrdr.Name +
" Value= "

+ myrdr.Value+
"
\
n"
);


}





myrdr.MoveToElement();


}





}


myrdr.Close();


OUTPUT



Type=Attribute Name= version Value= 1.0


Type=Attribute Name= encoding Value= utf
-
8


Type=Attribute Name= qt Value= 2


Type=Attribute Name= cur Value= lbp


Type=Attribute Name= qt Value= 20


Type=Attribute Name= cur Value= usds



Note that w
e can use also
: MoveToFirst/NextAttribute

Example 5

MoveToContent
:

c
hecks whether the current
node is a content (non
-
white space text,
CDATA
,
Element
,

30


EndElement
,
EntityReference
, or
EndEntity
) node. If the
node is not a content node, the reader skips ahead to the
next content node or end of file. It skips
over nodes of the
following type:
ProcessingInstruction
,

Comment
,
Whitespace
.

//this code will parse only Elements, EndElements and
Text

string

filepath =
"C:
\
\
..
\
\
catalog1.xml"
;


XmlTextReader

myrdr =
new

XmlTextReader
(filepath);




while

(myrdr.Read())




{


Console
.Write(
"movetocontent="

+
myrdr.MoveToContent().ToString() +
" Name= "

+
myrdr.Name+
" "
);


Console
.WriteLine(
"Value="
+myrdr.Value);




}


myrdr.Close();

Practice 7

Develop a windows application that will display a tree of
various elements and their values. The program must
ignore whitespaces and must process only element nodes
by testing:
myrdr.NodeType==
XmlNodeType
.Element.

Use the employees file described in
practice 5
. The output
must be as follows:


Solution



31



c
-

Improving Performance by using Name Tables


Whenever XmlTextReader parses any XML file,
it
creates

a list of element names found in that
document. If we save this list in a table and if we
supply the same table as a parameter of a new reader
that will parse an XML file having similar structure we
will increase the performance.


Example:



d.

Moving
B
etween
E
lements


There are some additional methods of XmlTextReader
that allow you to move between elements

and read
content.


a
-

ReadSubTree() Method


ReadSubtree

can be called only on element nodes.
When the entire sub
-
tree has been read, calls to the
Read

method returns
false
. When the new
XmlReader

has been closed, the original
XmlReader

will be
positioned on the
EndElement

node of the sub
-
tree.
Thus, if you called the
ReadSubtree

method on the

32


start tag of the book element, after the sub
-
tree has
been read and the new
XmlReader

has been closed,
the
original
XmlReader

is positioned on the end tag

of
the book element.

You should not perform any operations on the original
XmlReader

until the new
Xm
lReader

has been closed
.
This action is not supported and can result in
unpredictable behavior.

This is useful if you need to pass data to another
component for processing and you wish to limit how
much of your data the component can access.
When
you pass
an
XmlReader

returned by the
ReadSubtree

method to another application, the application can
access only that XML element, rather than the entire
XML document
. From the other side, this method
comes in handy when
you want to jump to a specific
node rather t
han sequentially moving there
.


Note:

if the reader is on any simple node,
ReadSubTree returns this node and
its entire

sibling
within the parent node
.



Example:


string

filepath =
"C:
\
\
..
\
\
catalog1.xml"
;




XmlTextReader

myrdr =
new

XmlTextReader
(filepath);




XmlReader

rdr=
null
;






while

(myrdr.Read())




{





myrdr.MoveToContent();





if

(myrdr.NodeType ==
XmlNodeType
.Element)

{





if

(myrdr.Name
==
"product"
)





{

//Method1





myrdr.MoveToFirstAttribute();


33






if

(myrdr.Value ==
"2"
)





{





myrdr.MoveToElement();








//MessageBox.Show

(myrdr.Name.ToString());





rdr = myrdr.ReadSubtree();





break
;





}

//Method2


//myrdr.ReadToFollowing("product");



////myrdr.MoveToFirstAttribute();



////MessageBox.Show(myrdr.Value);



//rdr = myrdr.ReadSubtree();



//break;




}





}




}





while

(rdr.Read())




{





if

(rdr.NodeType.ToString() ==
"Text"
)





{

//note that there is no Name only Type and
Value



MessageBox
.Show(
"Type="

+
rdr.NodeType.ToString()

+
" Name= "

+ rdr.Name +
" Value= "

+








rdr.Value);





}




}




rdr.Close();


MessageBox
.Show(
"Complete with myrdr"
);




myrdr.MoveToContent();




while

(myrdr.Read())




{





if

(myrdr.NodeType.ToString() ==
"Text"
)





{







MessageBox
.Show(
"Type="

+ myrdr.

NodeType.ToString()



+
" Name= "

+ myrdr.Name +

" Value= "

+

myrdr.Value);





}




}


myrdr.Close();

b
-

ReadToFollowing(“name”) method


Reads until the named element is found. See example
above.

c
-

ReadToDescendant(
“name”
)

method


34



Reads until the named element is found only if it is a
descendant of the current node, whereas the
ReadToFollowing() jumps to the first occurrence of the
specified element, be it a descendant or not.


d
-

ReadToNextSibling
(“name”)

method


It moves the reader
from the current element to the
next element at the same level.


e
-

Skip() method


Like ReadToNextSibling(), but it advances the reader to
the next possible element (whitespace, comment
element…).


e.

Reading Content


In our previous examples we used value prope
rty and
the ReadElementString() method (practice 7) to read
content from an element. In this section we are going
to see a few more ways to read the content.


a
-

ReadInnerXml()


It reads all the XML content inside the current node
and returns it as a string:
MessageBox
.Show(myrdr.ReadInnerXml());



b
-

ReadString()


35



It returns all the text from the element until any
markup is encount
e
red.


f.

Writing XML documents


The XmlTextWriter()
class r
epresents a writer that provides a
fast, non
-
cached, forward
-
only way of
generating streams or
files containing XML data that conforms to the W3C Extensible
Markup Language (XML) 1.0 and the Namespaces in XML
recommendations.


The following examples illustrate how we can use the class
.


Example 1

//no indentation in the xml fil
e. the xml tags are all on
the same line



string

filepath =
"C:
\
\
..
\
\
txtwriter1.xml"
;



XmlTextWriter

mywriter =
new

XmlTextWriter
(filepath,
null
);




//indentation is added



mywriter.Formatting =
Formatting
.Indented;



mywriter.Indentation =
2
;

mywriter.IndentChar =
'
\
t'
;




//or writing to the console



//XmlTextWriter mywriter = new XmlTextWriter(Console.Out);




mywriter.WriteStartDocument();


mywriter.WriteComment(
"chi"
);


mywriter.WriteStartElement(
"customerdetails"
);


mywriter.WriteAttributeString(
"acccounttype"
,
"saving"
);



//w.WriteElementString("customer", "10");


mywriter.WriteStartElement(
"accountnumber"
);


mywriter.WriteString(
"1"
);


mywriter.WriteEndElement();



mywriter.WriteStartElement(
"name"
);


mywriter.WriteString(
"2"
);


mywriter.WriteEndEle
ment();


mywriter.WriteStartElement(
"city"
);


mywriter.WriteString(
"3"
);


mywriter.WriteEndElement();


36



mywriter.WriteEndElement();


mywriter.WriteEndDocument();

mywriter.Close();



OUTPUT: txtwriter1.xml


<?xml version="1.0"?>

<!
--
chi
--
>

<customerdetails acccounttype="saving">


<accountnumber>1</accountnumber>


<name>2</name>


<city>3</city>

</customerdetails>



Example
2

string

filepath =
"C:
\
\
..
\
\
txtwriter2.xml"
;



XmlT
extWriter

w =
new

XmlTextWriter
(filepath,
null
);


w.WriteStartDocument();



w.Formatting =
Formatting
.Indented;



w.Indentation = 8;



w.WriteStartElement(
"customersdetails"
);



//create both an
element and writes its value


w.WriteElementString(
"customer"
,
"10"
);


w.WriteElementString(
"sold"
,
"100.3"
);



w.WriteEndElement();



w.WriteEndDocument();

w.Close();


Example
3: using filestream


string

filepath =
"C:
\
\
..
\
\
txtwriter3.xml"
;



FileStream

fs =
new

FileStream
(filepath,
FileMode
.Create);



XmlTextWriter

mywriter =
new

XmlTextWriter
(fs,
System.Text.
Encoding
.UTF8);


mywriter.Formatting =
Formatting
.Indente
d;


mywriter.Indentation = 4;




mywriter.WriteStartDocument();


mywriter.WriteComment(
"chi"
);


mywriter.WriteStartElement(
"customerdetails"
);


mywriter.WriteAttributeString(
"acccounttype"
,
"saving"
);


mywriter.WriteStartElement(
"accountnumber"
);


mywriter.WriteString(
"1"
);


mywriter.WriteEndElement();


mywriter.WriteStartElement(
"name"
);


mywriter.WriteString(
"2"
);


mywriter.WriteEndElem
ent();


mywriter.WriteStartElement(
"city"
);


mywriter.WriteString(
"3"
);


37



mywriter.WriteEndElement();


mywriter.WriteEndElement();


mywriter.WriteEndDocument();


mywriter.Close();



fs.Close();

mywriter.Close();


Practice 8


Develop a win
dows application
having the
following form:


that allows you to export data from any
table of SQL Server into an XML file.


Solution


g.

Including
namespace


The following example shows how we can include namespaces
with the XmlTextWriter


string

filepath =
"C:
\
\
..
\
\
txtwriter1.xml"
;



XmlTextWriter

mywriter =
new

XmlTextWriter
(filepath,
null
);


38




//indentation is added



mywriter.Formatting =
Formatting
.Indented;


mywriter.Indentation = 2;


mywriter.IndentChar =
' '
;



string

prefix =
"cust"
;


string

nms =
"http://www.company.com"
;



//or witing to the console


//XmlTextWriter mywriter = new XmlTextWriter(Console.Out);




mywriter.WriteStartDocument();


mywriter.WriteComment(
"chi"
);


mywriter.WriteStartElement(prefix,
"customerdetails"
,nms);

mywriter.WriteAtt
ributeString(prefix,
"acccounttype"
,
nms,
"saving"
);

mywriter.WriteAttributeString(prefix,
"acccounttype2"
, nms,
"saving"
);



//w.WriteElementString("customer", "10");


mywriter.WriteStartElement(prefix,
"accountnumber"
,nms);


mywriter.WriteString(
"1"
);


mywriter.WriteEndElement();



mywriter.WriteStartElement(prefix,
"name"
,nms);


mywriter.WriteString(
"2"
);


mywriter.WriteEndElement();


mywriter.WriteStartElement
(prefix,
"city"
,nms);


mywriter.WriteString(
"3"
);


mywriter.WriteEndElement();


mywriter.WriteEndElement();


mywriter.WriteEndDocument();

mywriter.Close();


Output

<?xml version="1.0"?>

<!
--
chi
--
>

<cust
:customerdetails cust:acccounttype="saving" cust:acccounttype2="saving"

xmlns:cust="http://www.company.com">


<cust:accountnumber>1</cust:accountnumber>


<cust:name>2</cust:name>


<cust:city>3</cust:city>

</cust:customerdetails>


h.

Serializing
/Deserializ
e

Images


The following code allows you to read any image and
serialize

it as an XML document.


39





The WriteBase64() method writes the supplied byte array as a
byte64 string inside the element.


To
deserialize

we can use the following code:





40


5
-

Accessing

XML Documents by Using XPATH


In the previous section we have provided a method for reading and
writing data by using XmlDocument, XmlReader and XmlWriter.
These classes allow you to access the XML documents but they
hardly provide a way to query and retr
ieve data from XML
documents. The System.Xml.XPath class is designed to do just that.


a.

Overview of XPATH


XPath provides

a way to query and select a aprt of an XML
document. To work with XPath we have to understand the
following:




Location path



Axis



Node
Tests



Predicates

Loaction path

Various parts of an XML document such as elements and
attributes have a location. The location is indicated by a
specific XPath syntax called the
location path
,
which
allows you
to select a set of nodes. A location path consi
sts of an
axis
, a
node test

and

predicates
.

The general syntax of a location path
can be formally defined as follows:

Axis::node
-
test
/Axis::node
-
test
[]
/../Axis::node
-
test
[predicate]

We can use one or more Axis::node
-
test
.



41


A
xis

An axis is a
starting point
to apply node test and predicates
.
The following table lists the available axis:


Node
Test

It contains a series of nodes, that is, a path.

P
redicates

Are Boolean expressions that are used to further filter the
nodes selected by the axis and the node
test.

E
xamples

Given the following bibilio.xml file:

<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<
biblio
>






<
livre

id
=
"
2
"

pub
=
"
pub2
"
>
livre1






<
titre
>
t2
</
titre
>






<
auteur
>
a2







<
a

id
=
"
15
"
>
v1

<
aa
>
aa
</
aa
>







</
a
>





<
b
></
b
>










<
c

id2
=
""
>
v2
</
c
>







<
titre
>
t2
</
titre
>






</
auteur
>







</
livre
>


42






<
livre

id
=
"
3
"

pub
=
"
pub3
"
>






<
titre
>
t3
</
titre
>






<
auteur
>
a3
</
auteur
>






<
e
>
ve
</
e
>





</
livre
>





<
livre

id
=
"
4
"

pub
=
"
pub4
"
>






<
titre
>
t4
</
titre
>






<
auteur
>
a4







<
auteur
>
in_a4
</
auteur
>






</
auteur
>






<
a
>
it is a







<
b
>








<
auteur
>
a5
</
auteur
>







</
b
>






</
a
>





</
livre
>





<
livre
>






<
titre
>
t5
</
titre
>






<
auteur
>
a5
</
auteur
>





</
livre
>

</
biblio
>


Evaluate the following XPath
locations:

1.

child::biblio/child::livre[titre='t2']/following::liv
re

I
t returns all
all the “livre” following the “livre” having a
“titre=t2”

child of bibilio child of the document
:





<
livre

id
=
"
3
"

pub
=
"
pub3
"
>






<
titre
>
t3
</
titre
>






<
auteur
>
a3
</
auteur
>






<
e
>
ve
</
e
>





</
livre
>





<
livre

id
=
"
4
"

pub
=
"
pub4
"
>






<
titre
>
t4
</
titre
>






<
auteur
>
a4







<
auteur
>
in_a4
</
auteur
>






</
auteur
>






<
a
>
it is a







<
b
>








<
auteur
>
a5
</
auteur
>







</
b
>






</
a
>





</
livre
>





<
livre
>






<
titre
>
t5
</
titre
>






<
auteur
>
a5
</
auteur
>





</
livre
>



43


2.

child::biblio/child::livre[titre='t2']/following::liv
re[titre='t4']


It
returns all

the “livre”
having “titre=t4”
following the
“livre” having a “titre=t2”

child of bibilio child of the
document
:

<
livre

id
=
"
4
"

pub
=
"
pub4
"
>






<
titre
>
t4
</
titre
>






<
auteur
>
a4







<
auteur
>
in_a4
</
auteur
>






</
auteur
>






<
a
>
it is a







<
b
>








<
auteur
>
a5
</
auteur
>







</
b
>






</
a
>





</
livre
>


3.

child::biblio/child::livre[auteur='a3']/child::auteur
/ancestor::*


it returns all the ancestor
of the “auteur” child of
“livre[auteur=a3]” child of bibilio child of document
:


All

the document and the “livre” having id=3

4.

child::biblio/child::livre[auteur='a3']/child::auteur
/ancestor::livre[titre='t3']


it returns
t
he ancestor
livre[titre=t3] (if it is)
of the
“auteur” child of “livre[auteur=a3]” child of bibilio child
of document
.


5.

child::biblio/child::livre[auteur='a3']/child::auteur
/preceding::*


<
titre
>
t3
</
titre
>


<
livre

id
=
"
2
"

pub
=
"
pub2
"
>
livre1






<
titre
>
t2
</
titre
>






<
auteur
>
a2







<
a

id
=
"
15
"
>
v1

<
aa
>
aa
</
aa
>







</
a
>





<
b
></
b
>


44











<
c

id2
=
""
>
v2
</
c
>







<
titre
>
t2
</
titre
>






</
auteur
>

<
/
livre
>


and

after all of
its
child and subchild node
s


6.

child::biblio/child::livre[auteur='a3']/child::auteur
/preceding
-
sibling::
*


<
titre
>
t3
</
titre
>


7.

"child::biblio/child::livre[auteur='a3']/child::titre
/following::*"
);


<
auteur
>
a3
</
auteur
>


<
e
>
ve
</
e
>


<
livre

id
=
"
4
"

pub
=
"
pub4
"
>






<
titre
>
t4
</
titre
>






<
auteur
>
a4







<
auteur
>
in_a4
</
auteur
>






</
auteur
>






<
a
>
it is a







<
b
>








<
auteur
>
a5
</
auteur
>







</
b
>






</
a
>





</
livre
>


and their

after all of
its
child and subchild node
s


<
livre
>






<
titre
>
t5
</
titre
>






<
auteur
>
a5
</
auteur
>





<
/
livre
>


and theirafter all of
its
child and subchild node
s


8.

child::biblio/child::livre[auteur='a3']/child::titre/
following
-
sibling::*


<
auteur
>
a3
</
auteur
>


<
e
>
ve
</
e
>


9.

child::biblio/child::livre/child::auteur/descendant::
auteur


45



<
auteur
>
in_a4
</
auteur
>

10.
child::biblio/child::livre/child::auteur/descendant::
*

<
a

id
=
"
15
"
>
v1
<
aa
>
aa
</
aa
>
</
a
>

<
aa
>
aa
</
aa
>





<
b
></
b
>







<
c

id2
=
""
>
v2
</
c
>

<
titre
>
t2
</
titre

<
auteur
>
in_a4
</
auteur
>


11.
child::biblio/child::livre/child::auteur/descendant
-
or
-
self::auteur


<
auteur
>
a2






<
a

id
=
"
15
"
>
v1

<
aa
>
aa
</
aa
>






</
a
>





<
b
></
b
>








<
c

id2
=
""
>
v2
</
c
>






<
titre
>
t2
</
titre
>





</
auteur
>












<
auteur
>
a3
</
auteur
>


<
auteur
>
a4






<
auteur
>
in_a4
</
auteur
>





</
auteur
>


<
auteur
>
in_a4
</
auteur
>


<
auteur
>
a5
</
auteur
> (of the last livre)


12.
child::biblio/child::livre[titre='t2']/child::titre/p
arent::*


<
livre

id
=
"
2
"

pub
=
"
pub2
"
>
livre1






<
titre
>
t2
</
titre
>






<
auteur
>
a2







<
a

id
=
"
15
"
>
v1



<
aa
>
aa
</
aa
>





</
a
>







<
b
></
b
>







<
c

id2
=
""
>
v2
</
c
>







<
titre
>
t2
</
titre
>






</
auteur
>



</
livre
>



46


13.
child::biblio/child::livre[titre='t2']/child::titre/s
elf::*


OR


child::biblio/child::livre[titre='t2']/child::titre


<
titre
>
t2
</
titre
>


14.
child::biblio/child::livre/attribute::id


id
=
"
2
"

id
=
"3"

id
=
"
4
"

15.


b.

Abbreviated

XPath Function


1
-

biblio/livre[titre='t2']/following::livre[titre='t4']

Same result as paragraph a
-
1

2
-

biblio/livre[auteur='a3']/titre

and returns

<
titre
>
t3
</
titre
>

3
-

child::biblio/child::livre/child::auteur/descendant::aut
eur

Is equivalent to

:
biblio/livre/auteur//auteur

a
nd returns
<
auteur
>
in_a4
</
auteur
>

4
-

child::biblio/child::livre/attribute::id

Is equivalent to:

biblio/livre/@id.
and returns

id
=
"
2
"

id
=
"3"

id
=
"
4
"

5
-

child::biblio/child::livre/attribute::id[.='2']

Is equivalent
to:

biblio/livre/@id[.='2']
and returns

id
=
"
2
"

6
-

child::biblio/child::*

is equivalent to

biblio
/*
and
returns all the first child of biblio i.e livre 2,3,4 and 5


47


7
-

child::biblio/child::livre/descendant::auteur
is
equivalent to

//auteur
and returns all the
occurrence of the
tag <auteur> in all the tree at any level.

8
-

child::biblio/child::livre[attribute::pub[.='pub2']]
is
equivalent to

biblio/livre[@pub='pub2
’]

and returns the
first livre


c.

T
he
XPath
data model


It relies on a class called XpathNavigator

residing in the
System.Xml.XPath

namespace. It is an
abstract class

and
we
can obtain an instance from any class that implements the
IXPathNavigable Interface
. The classes that implement this
interface are
XmlDocument
, XmlDataDocument

and
XPathDocument
.
T
he XPathNavigator instance returned from
XmlDocument is editable, whereas that returned by
XPathDocument is read
-
only
.


NOTE:

The xpath loads only the desired xml
fragment

into the memory

thus reducing memory footprint
.


a
-

Creating the XPathNavigator




By
using XmlDocument

or
Xml
Data
Document





By using the XPathDocument




48


b
-

Selecting Nodes
: Select,
SelectSingleNode


The following code shows how we can execute the
previous XPath expression explained above by using
the
Select

meth
o
d of the XPathNavigator.

XPathDocument

xdoc =
new

XPathDocument

(
"C:
\
\
..
\
\
biblio.xml"
);


XPathNavigator

xnav;





xnav = xdoc.CreateNavigator();



XPathNodeIterator

xiter;







xiter = xnav.Select(
"child::biblio/child::livre

[attribute::pub[.='pub2']]"
);


xiter = xnav.Select(
"biblio/livre

[@pub='pub2']"
);

while

(xiter.MoveNext())


{



//MessageBox.Show(xiter.Current

.Value.ToString());

//or

XPathNavigator

xn = xiter.Current.Clone();





MessageBox
.Show(x
n.OuterXml);





//
textBox1.Text=

xn.OuterXml
;









}




The Select(
) method returns all the nodes that are
obtained after evaluating the XPath expression. There
is a method called
SelectSingleNode()

that executes the
XPath expression and returns an
XPathNavigator
object instead of an XPathNodeIterator

that contains
the fi
rst matching node.

The following code shows how
we can use the method.




49


MessageBox.Show(result.
name); shows the firstname.

XpathNavigator
N
ote:
SelectChildren(),

S
electAncestors(),SelectDescendants()





c
-

Navigating by using XPathNavigator
,Navigating
between attributes

The

XPathNavigator

can be used

to access various
attribute
s and elements by using multiple methods as
illustrated in the following example.


Books.xml

<?
xml

version
=
"
1.0
"

encoding
=
"
utf
-
8
"

?>

<?
xml
-
stylesheet

type="text/xsl"
href="books.xslt"
?>

<
bookstore

xmlns:bk
=
"
myurn
"
>


<
book

genre
=
"
Novel
"

isbn
=
"
10
-
861001
-
12
-
1
"
>



<
title
>
Java
</
title
>



<
price
>
19.95
</
price
>


</
book
>


<
book

genre
=
"
Eyrolles
"

isbn
=
"
10
-
861002
-
12
-
2
"
>



<
title
>
C#
</
title
>



<
price
>
24.50
</
price
>


</
book
>


<
book

genre
=
"
Eyrolles
"

isbn
=
"
1
-
861003
-
12
-
3
"
>



<
title
>
PHP
</
title
>



<
price
>
15.00
</
price
>


</
book
>


<
book

genre
=
"
Eyrolles
"

isbn
=
"
1
-
861004
-
12
-
4
"
>



<
title
>
UML
</
title
>



<
price
>
25.00
</
price
>


</
book
>


<
book

genre
=
"
Bordas
"

isbn
=
"
1
-
861005
-
12
-
5
"
>



<
title
>
UML
</
title
>


50




<
price
>
45.00
</
price
>


</
book
>


<
book

genre
=
"
Novel
"

isbn
=
"
10
-
861006
-
12
-
6
"
>



<
title
>
UML
</
title
>



<
price
>
35.00
</
price
>


</
book
>


<
book

genre
=
"
Bordas
"

isbn
=
"
1
-
861007
-
12
-
7
"
>



<
title
>
Xml
</
title
>



<
price
>
25.00
</
price
>


</
book
>


</
bookstore
>


Code

XPathDocument

xdoc =
new

XPathDocument

(
"C:
\
\
..
\
\
books.xml"
);


XPathNavigator

xnav;





xnav = xdoc.CreateNavigator();






//
the entire tree


xnav.
MoveToRoot
();





//root


//MessageBox.Show(xnav.OuterXml);





xnav.
MoveToFirstChild
();


//<?xml version...





//MessageBox.Show(xnav.OuterXml);





xnav.
MoveToNext
();





//bookstore


MessageBox
.Show(xnav.OuterXml);





xnav.
MoveToFirstChild
();


//book 1





MessageBox
.Show(xnav.OuterXml);


//Novel


MessageBox
.Show(
xnav.GetAttribute(
"genre"
,
""
)
);





xnav.
MoveToFirstAttribute
();





//genre


MessageBox
.Show(xnav.OuterXml);


//or


string

str = xnav.Value;


MessageBox
.Show(str);



xnav.
MoveToParent
();





//book 1


MessageBox
.Show(xnav.OuterXml);






xnav.
MoveToAttribute
(
"isbn"
,
""
);


//isbn


MessageBox
.Show(xnav.OuterXml);






xnav.
MoveToParent
();


//book 1