Visual C# 3.0 Application Design II FunctionX Press
SUMARY QUERYING A LIST......................................................................................20 THE LANGUAGE INTEGRATED QUERY.....................................................................20 Introduction to Querying....................................................................20 Introduction to LINQ..........................................................................20 Selecting the Values...........................................................................21 Using a Collection-Based Variable......................................................23 Using a Criterion to Create a Sub-List.................................................24 OPERATIONS ON QUERIES.................................................................................27 Using Logical Conjunctions and Disjunctions.....................................27 Arranging the List...............................................................................29 INFLUENCING A LINQ STATEMENT......................................................................32 Using the Primitive Types...................................................................32 Using the String Class........................................................................32 LINQ AND CLASSES......................................................................................34 Using Built-In Classes........................................................................38 LINQ OPERATORS........................................................................................38 Letting a Sub-List...............................................................................38 Creating a new List.............................................................................40 EXPLORING THE LINQ...............................................................................43 THE IENUMERABLE GENERIC INTERFACE................................................................43 Using IEnumerable.............................................................................44 The Characteristics of IEnumerable....................................................45 INTRODUCTION TO XML............................................................................49 THE EXTENSIBLE MARKUP LANGUAGE....................................................................49 Overview of Files................................................................................49 Markup...............................................................................................53 The Document Type Declaration (DTD)..............................................53 Encoding Declaration..........................................................................53 Creating an XML File...........................................................................54 Practical Learning: Introducing XML..................................................54 WRITING XML CODE.....................................................................................54 Writing XML Code Using XmlDocument..............................................55 Practical Learning: Creating an XML Document..................................55 Writing XML Code Using the Code Editor............................................55 SAVING AN XML FILE....................................................................................56 Using the Wizard................................................................................57 Practical Learning: Creating the Root Tag..........................................57 Saving a DOM Object..........................................................................57 OPENING AN XML FILE..................................................................................58 An XML File in a Browser....................................................................58 Using a Style Sheet to Display an XML File in a Browser.....................59 Programmatically Opening an XML File Using the DOM......................60 Programmatically Reading an XML File...............................................62 XML WELLFORMEDNESS..................................................................................65 Tag Creation.......................................................................................65 Practical Learning: Creating XML........................................................66 Tag Names.........................................................................................66 The Root.............................................................................................67 THE STRUCTURE OF AN XML TAG.......................................................................70 Empty Tags.........................................................................................70 White Spaces......................................................................................70
C# 3.0 Practical Learning II
2
Nesting Tags......................................................................................71 Practical Learning: Creating XML........................................................71 THE NODES OF AN XML ELEMENT..............................................................74 AN XML NODE............................................................................................74 Introduction to Node Types................................................................75 ELEMENTS FUNDAMENTALS................................................................................75 Practical Learning: Introducing XML Elements...................................77 The Name of an Element.....................................................................78 The Text or Value of an Element.........................................................80 Practical Learning: Getting the Text of an Element.............................82 Empty Elements..................................................................................83 Character Entities in an Element Value...............................................84 Practical Learning: Introducing XML Elements...................................89 IDENTIFYING THE MARKUP OF A NODE..................................................................91 The Inner Text of a node....................................................................91 The Outer XML Code of a node............................................................92 The Inner XML Code of a node............................................................93 THE CHILD NODES OF A NODE.........................................................................94 A Collection of Child Nodes.................................................................94 Accessing a Node in a Collection........................................................95 The Parent of a Node..........................................................................98 The First Child Node...........................................................................98 The Last Child Node..........................................................................103 The Siblings of a Node......................................................................103 OPERATIONS ON XML ELEMENTS.............................................................105 FUNDAMENTAL OPERATIONS.............................................................................105 Practical Learning: Introducing operations on XML Elements...........105 Adding an Empty Element.................................................................106 Adding an Element With Value.........................................................108 Practical Learning: Programmatically Adding an Element................114 Adding a Filled Child Element...........................................................118 INSERTING AN ELEMENT.................................................................................120 Locating an Element.........................................................................120 Inserting an Element as a Last Child................................................122 Practical Learning: Adding Elements................................................131 Insertion an Element Referencing a Sibling......................................137 Node Removal..................................................................................140 THE ATTRIBUTES OF AN XML ELEMENT...................................................143 FUNDAMENTALS OF ATTRIBUTES........................................................................143 Practical Learning: Introducing Attributes ......................................143 Creating an Attribute........................................................................144 OPERATIONS ON AN XML ATTRIBUTE.................................................................145 Manually Creating an Attribute.........................................................145 Practical Learning: Creating Simple Attributes ................................146 Programmatically Creating an Attribute .........................................146 Practical Learning: Creating an Attribute.........................................149 The Parent of an Attribute................................................................151 Attribute Removal............................................................................151 THE COLLECTION OF ATTRIBUTES OF AN ELEMENT....................................................152 Practical Learning: Adding Attributes...............................................153 Access to an Attribute......................................................................153 Practical Learning: Accessing an Attribute.......................................155 Attribute Addition.............................................................................156 Practical Learning: Creating Attributes.............................................157
C# 3.0 Practical Learning II
3
Attribute Removal............................................................................168 CHARACTERISTICS OF XML NODES..........................................................170 OVERVIEW OF TYPES OF NODES........................................................................170 Comments........................................................................................170 CDATA..............................................................................................172 XML Serialization..............................................................................173 INTRODUCTION TO DATA SETS AND TABLES...........................................175 A SET OF DATA..........................................................................................175 Data Set Creation.............................................................................175 TABLES FUNDAMENTALS.................................................................................177 Introduction to Tables......................................................................177 Practical Learning: Introducing Tables.............................................178 Creating a Table...............................................................................178 THE TABLES OF A DATA SET...........................................................................180 Accessing a Table in the Collection...................................................181 Adding a New Table to a Collection..................................................182 Creating a Range of Tables...............................................................184 Practical Learning: Creating Tables..................................................184 Locating a Table in a Collection........................................................185 Practical Learning: Showing Tables..................................................190 TABLES MAINTENANCE...................................................................................192 Deleting a Table...............................................................................192 Checking the Existence of a Table in a Collection.............................194 Clearing a Collection of Tables..........................................................196 THE COLUMNS OF A TABLE......................................................................197 FUNDAMENTALS OF COLUMNS OF A TABLE.............................................................197 Practical Learning: Introducing Columns..........................................198 Creating a Column............................................................................199 OPERATIONS ON THE COLUMNS OF A TABLE...........................................................201 Adding a Column to a Table..............................................................201 Practical Learning: Creating Columns...............................................203 Adding an Array of Columns.............................................................204 Specifying the Type of Data of a Column..........................................205 Practical Learning: Specifying the Data Types of Columns Columns. 206 COLUMNS MAINTENANCE................................................................................208 The Parent Table of a Column...........................................................208 Identifying a Column........................................................................208 Practical Learning: Listing the Columns of a table............................209 DELETING COLUMNS.....................................................................................213 Deleting a Column by Name.............................................................213 Deleting a Column by Index.............................................................217 Clearing the Table of Columns..........................................................218 THE RECORDS OF A TABLE.......................................................................219 THE ROWS OF A TABLE.................................................................................219 Introduction to Records...................................................................219 Practical Learning: Introducing Data Records..................................220 The Row of a Table...........................................................................220 Introduction to Data Entry...............................................................221 DATA ENTRY.............................................................................................221 Adding a Record to a Table...............................................................222 Adding an Array of Records..............................................................223 The Number of Records of a Table....................................................225 SAVING THE RECORDS OF A TABLE.....................................................................225
C# 3.0 Practical Learning II
4
Saving a Data Set.............................................................................225 Practical Learning: Creating a Data Set............................................228 Opening a Data Set...........................................................................236 Committing or Rejecting Changes to a List.......................................239 LOCATING RECORDS AND THEIR VALUES..............................................................239 Locating a Record.............................................................................239 Locating a Value...............................................................................243 Practical Learning: Getting the Values of a Data Set........................247 RECORDS MANAGEMENT..........................................................................257 RECORDS MAINTENANCE.................................................................................257 Editing a Record by the Columns' Object Names..............................258 Editing a Record by the Columns' Indices.........................................265 DELETING RECORDS......................................................................................265 Deleting the Current Row.................................................................265 Removing a Row From the Collection of Records..............................267 Deleting a Record by its Index.........................................................269 Deleting all Records of a Table.........................................................269 DATA RELATIONSHIPS...................................................................................270 Table Preparation.............................................................................270 Creating a Relationship....................................................................275 INTRODUCTION TO ADO..........................................................................284 ADO FUNDAMENTALS...................................................................................284 Introduction to Databases................................................................284 Microsoft JET....................................................................................284 Referencing a Library in a .NET Framework......................................285 MICROSOFT ADO EXT..................................................................................285 The Catalog Class.............................................................................286 DATABASE CREATION....................................................................................287 The Catalog Class.............................................................................287 The Provider.....................................................................................287 The Data Source of a Connection String...........................................289 The ODBC Data Source ....................................................................290 USING THE MICROSOFT ACTIVEX DATA OBJECTS (ADO).........................................292 Referencing ADO..............................................................................293 The ADODB Namespace....................................................................293 THE CONNECTION TO A DATABASE.....................................................................294 Opening a Connection.......................................................................294 The Connection String......................................................................295 The Login Credentials.......................................................................296 Executing a SQL Statement..............................................................297 Closing a Connection........................................................................298 THE RECORDS OF A DATABASE................................................................301 TABLE CREATION.........................................................................................301 Table Creation..................................................................................302 The Name of a Table.........................................................................302 TABLE MAINTENANCE....................................................................................303 The Tables Collection........................................................................303 Deleting a Table...............................................................................303 COLUMNS FUNDAMENTALS...............................................................................304 Column Creation...............................................................................305 CHARACTERISTICS OF A COLUMN........................................................................305 The Types of Columns.......................................................................306 COLUMN MAINTENANCE..................................................................................311 Adding a New Column......................................................................311
C# 3.0 Practical Learning II
5
Deleting a Column............................................................................312 DATA ENTRY FUNDAMENTALS...........................................................................313 New Record Creation........................................................................314 Adjacent Data entry.........................................................................316 Random Data Entry..........................................................................316 DATA ENTRY ASSISTANCE...............................................................................317 The Nullity of a Field.........................................................................318 Auto-Increment................................................................................319 Fields Sizes.......................................................................................320 Default Values..................................................................................321 MATHEMATICS IN C#..............................................................................322 OVERVIEW OF NUMBERS.................................................................................322 The Sign of a Number ......................................................................322 The Integral Side of a Floating-Point Number .................................324 The Minimum of Two Values ............................................................325 The Maximum Integer Value of a Series ..........................................326 VALUE CONVERSIONS....................................................................................326 Implicit Conversions ........................................................................327 Explicit Conversions ........................................................................328 The Convert Class ............................................................................330 ARITHMETIC..............................................................................................332 Absolute Values ...............................................................................332 The Ceiling of a Number ..................................................................333 The Floor of a Number .....................................................................334 The Power of a Number ...................................................................334 The Exponential ...............................................................................335 The Natural Logarithm .....................................................................336 The Base 10 Logarithm ....................................................................336 The Logarithm of Any Base .............................................................337 The Square Root ..............................................................................338 TRIGONOMETRY...........................................................................................338 The Pi Constant ...............................................................................340 The Cosine of a Value ......................................................................340 The Sine of a Value...........................................................................341 Tangents .........................................................................................342 The Arc Tangent ..............................................................................342 DATES AND TIMES...................................................................................344 DATES AND TIMES.......................................................................................344 Date Time Value Creation.................................................................345 The Characteristics of a Date-Time Value.........................................346 The Default Date and Time Values....................................................347 DATES.....................................................................................................347 Date Creation...................................................................................347 Converting a String to Date..............................................................348 Rules of Date Formats......................................................................348 DATE FORMATS...........................................................................................353 The Computer’s System of Displaying Dates.....................................353 Getting a Date Value From a DateTime Object..................................353 The Short Date.................................................................................356 The Long Date Format......................................................................358 Other Date Formats..........................................................................359 OPERATIONS ON DATES.................................................................................360 The Leap Year...................................................................................360 The Day of the Week........................................................................361 A Time Span.....................................................................................362
C# 3.0 Practical Learning II
6
Adding and/or Subtracting Days......................................................362 Adding or Subtracting Months to a Date...........................................364 Adding or Subtracting Years to a Date..............................................364 Logical Operations on Dates.............................................................365 TIME......................................................................................................366 Creating a Time Value......................................................................367 Retrieving a Time Value....................................................................368 THE CHARACTERISTICS OF A TIME VALUE.............................................................369 The Components of a Time...............................................................369 The Time of Day of a DateTime Value...............................................370 OPERATIONS ON TIME VALUES.........................................................................370 Converting a Time Value to a String.................................................370 Time Rules and Formats...................................................................371 Comparison Operations On Time Values...........................................379 COMBINING DATE AND TIME............................................................................379 The Current Date and Time...............................................................379 Formatting Date and Time Combinations..........................................380 WINDOWS CONTROL: THE BUTTON.........................................................381 DESCRIPTION.............................................................................................381 CREATING A BUTTON....................................................................................385 THE CHARACTERISTICS OF A BUTTON.....................................................387 THE CAPTION OF A BUTTON............................................................................387 THE IMAGE ON A BUTTON ..............................................................................393 THE FLAT STYLE OF A BUTTON ........................................................................394 THE RESULT OF A DIALOG BOX .......................................................................395 Applications:....................................................................................396 WINDOWS CONTROL: THE COMBO BOX...................................................397 DESCRIPTION.............................................................................................397 CREATING A COMBO BOX...............................................................................398 THE COMBO BOX: CREATING AND SELECTING ITEMS................................................405 CREATING THE LIST OF ITEMS..........................................................................405 SELECTING AN ITEM.....................................................................................407 FINDING A STRING IN THE COMBO BOX...............................................................427 THE STYLES OF A COMBO BOX.................................................................428 THE THE THE THE
FLAT STYLES........................................................................................428 DROP DOWN STYLE................................................................................430 DROP DOWN LIST.................................................................................434 SIMPLE COMBO BOX...............................................................................434
THE COMBO BOX: AUTOMATIC LIST CREATION.......................................436 USING USING
EXTERNAL LIST..............................................................................436 CUSTOM LIST..................................................................................438
AN A
ACCESSORIES FOR CONTROL DESIGN: THE FLOW LAYOUT PANEL...........439 INTRODUCTION...........................................................................................439 CHARACTERISTICS OF THE FLOW LAYOUT PANEL......................................................440 THE CHARACTERISTICS OF A BUTTON.....................................................441 THE CAPTION OF A BUTTON............................................................................441 THE IMAGE ON A BUTTON ..............................................................................447 THE FLAT STYLE OF A BUTTON ........................................................................448 THE RESULT OF A DIALOG BOX .......................................................................449 Applications:....................................................................................450
C# 3.0 Practical Learning II
7
WINDOWS CONTROL: THE LINK LABEL...................................................450 INTRODUCTION...........................................................................................450 CHARACTERISTICS OF THE LINK LABEL.................................................................450 WINDOWS CONTROL: THE MONTH CALENDAR.........................................451 DESCRIPTION.............................................................................................451 CREATING A CALENDAR..................................................................................454 USING A MONTH CALENDAR CONTROL....................................................462 SELECTING A DATE.......................................................................................462 THE DATE RANGE SELECTION..........................................................................464 THE MAXIMUM DATE RANGE SELECTION..............................................................468 WINDOWS CONTROLS: THE PICTURE BOX...............................................469 DESCRIPTION.............................................................................................469 GETTING A PICTURE BOX...............................................................................469 INTRODUCTION ..........................................................................................470 THE BORDER STYLE OF A PICTURE BOX ..............................................................471 THE IMAGE OF A PICTURE BOX ........................................................................471 THE IMAGE LOCATION OF THE IMAGE OF A PICTURE BOX ..........................................473 THE SIZE MODE OF A PICTURE BOX ..................................................................475 WINDOWS CONTROL: RICH TEXT BOX.....................................................483 DESCRIPTION.............................................................................................483 CREATING A RICH TEXT CONTROL.....................................................................483 INTRODUCTION ..........................................................................................488 SAVING THE CONTENTS OF A RICH TEXT DOCUMENT ................................................489 OPENING A RICH TEXT FILE ...........................................................................490 FORMATTING TEXT ......................................................................................496 THE PARAGRAPH ALIGNMENT ..........................................................................497 THE INDENTATION OF A PARAGRAPH ..................................................................499 A BULLETED PARAGRAPH ...............................................................................499 ACCESSORIES FOR CONTROL DESIGN: THE TABLE LAYOUT PANEL..........500 INTRODUCTION...........................................................................................500 CHARACTERISTICS OF A TABLE LAYOUT................................................................501 THE CHARACTERISTICS OF A BUTTON.....................................................502 THE CAPTION OF A BUTTON............................................................................502 THE IMAGE ON A BUTTON ..............................................................................508 THE FLAT STYLE OF A BUTTON ........................................................................510 THE RESULT OF A DIALOG BOX .......................................................................510 Applications:....................................................................................511 THE BROWSE FOR FOLDER DIALOG BOX..................................................512 DESCRIPTION.............................................................................................512 CREATING A BROWSE FOR FOLDER DIALOG BOX.....................................................513 CHARACTERISTICS OF THE BROWSE FOR FOLDER DIALOG BOX..............514 THE THE THE THE
DESCRIPTION.......................................................................................514 ROOT FOLDER......................................................................................515 SELECTED PATH.....................................................................................516 MAKE NEW FOLDER BUTTON......................................................................517
APPLICATION MENUS: CONTEXTUAL MENUS...........................................519 INTRODUCTION...........................................................................................519 CREATING A CONTEXTUAL MENU.......................................................................520
C# 3.0 Practical Learning II
8
USING A CONTEXTUAL MENU...........................................................................524 CODING CONTEXTUAL MENUS...........................................................................526 THE FONT DIALOG BOX...........................................................................530 INTRODUCTION...........................................................................................531 CREATING A FONT DIALOG BOX........................................................................532 THE FONT OF A FONT DIALOG BOX...................................................................534 THE APPLY BUTTON.....................................................................................535 THE EFFECTS OF A FONT DIALOG BOX................................................................536 THE COLOR COMBO BOX................................................................................536 WINDOWS CONTROL: THE LIST BOX.......................................................538 DESCRIPTION.............................................................................................538 CREATING A LIST BOX..................................................................................539 THE ITEMS OF A LIST BOX.......................................................................544 INTRODUCTION...........................................................................................544 ADDING ITEMS TO A LIST BOX.........................................................................545 SELECTING AN ITEM IN A LIST BOX...................................................................552 REMOVING ITEMS FROM A LIST BOX..................................................................564 SORTING A LIST BOX...................................................................................567 CHARACTERISTICS OF A LIST BOX..........................................................567 THE SCROLL BARS.......................................................................................567 A MULTI-COLUMN LIST BOX...........................................................................571 A CUSTOM OWNER-DRAW LIST BOX.................................................................572 WINDOWS CONTROL: THE NUMERIC UP-DOWN......................................572 DESCRIPTION.............................................................................................572 CREATING AN UP-DOWN CONTROL....................................................................572 CHARACTERISTICS OF THE NUMERIC UP-DOWN CONTROL.....................574 THE UP-DOWN ALIGNMENT............................................................................574 INTERCEPTING THE ARROW KEYS.......................................................................574 THE MINIMUM AND THE MAXIMUM VALUES...........................................................575 THE VALUE OF THE CONTROL...........................................................................576 THE TYPE OF VALUE.....................................................................................576 DISPLAYING DECIMAL NUMBERS.......................................................................576 THE THOUSAND SEPARATOR............................................................................576 THE INCREMENTING VALUE.............................................................................577 Applications:....................................................................................577 THE PRINT DIALOG BOX..........................................................................578 INTRODUCTION...........................................................................................578 PROVIDING A PRINTER..................................................................................579 THE DOCUMENT TO PRINT..............................................................................580 EVENTS RELATED TO PRINTING.........................................................................581 THE PRINTER SETTINGS.................................................................................582 THE SAVE DIALOG BOX............................................................................586 DESCRIPTION.............................................................................................586 SAVE AS DIALOG BOX CREATION......................................................................587 CHARACTERISTICS OF THE SAVE AS DIALOG BOX...................................588 THE FILE EXTENSION ...................................................................................588 THE FILTER ..............................................................................................589 THE FILTER INDEX ......................................................................................591
C# 3.0 Practical Learning II
9
THE DEFAULT EXTENSION ..............................................................................592 DISPLAYING THE DIALOG BOX .........................................................................593 WINDOWS CONTROL: THE TEXT BOX.......................................................595 INTRODUCTION...........................................................................................595 CREATING A TEXT BOX..................................................................................595 INTRODUCTION...........................................................................................595 SELECTING TEXT.........................................................................................596 OPERATIONS ON TEXT...................................................................................596 MNEMONICS..............................................................................................597 THE READ-ONLY ATTRIBUTE...........................................................................598 AUTO-COMPLETING A TEXT BOX.......................................................................598 CHARACTER CASING......................................................................................598 CHARACTER PASSWORD..................................................................................599 INTRODUCTION...........................................................................................599 CREATING A MULTI-LINE TEXT BOX..................................................................600 INTRODUCTION...........................................................................................600 THE LINES OF TEXT ....................................................................................600 THE MODIFIED ATTRIBUTE .............................................................................600 THE MAXIMUM LENGTH OF TEXT ......................................................................601 USING THE ENTER KEY .................................................................................601 USING THE TAB KEY ...................................................................................601 WRAPPING TEXT ........................................................................................602 USING SCROLL BARS....................................................................................602 METHODS TO MANAGE A MULTI-LINE TEXT BOX....................................................603 Application.......................................................................................603 WINDOWS CONTROLS: THE TRACK BAR..................................................604 INTRODUCTION...........................................................................................604 CREATING A TRACK BAR................................................................................605 CHARACTERISTICS OF A TRACK BAR.......................................................606 THE ORIENTATION ......................................................................................606 THE VALUE OF A TRACK BAR ..........................................................................608 THE MAXIMUM AND THE MINIMUM VALUES ..........................................................608 THE TICKS OF A TRACK BAR ..........................................................................610 THE TICK FREQUENCY ..................................................................................610 THE TICK STYLE ........................................................................................611 THE SMALL CHANGE ....................................................................................611 THE LARGE CHANGE ....................................................................................612 Applications:....................................................................................612 WINDOWS CONTROLS: CHECK BOXES.....................................................612 INTRODUCTION...........................................................................................612 CREATING A CHECK BOX................................................................................613 WINDOWS CONTROLS: CHECK BOXES.....................................................621 CHECKING A CHECK BOX................................................................................621 THE ALIGNMENT OF A CHECK BOX.....................................................................629 THE CHECKED STATE OF A CHECK BOX................................................................629 THE APPEARANCE OF A CHECK BOX....................................................................630 Applications......................................................................................631 WINDOWS CONTROL: THE DATA GRID VIEW...........................................631 INTRODUCTION...........................................................................................631 CREATING A DATA GRID VIEW.........................................................................632 INTRODUCTION...........................................................................................634
C# 3.0 Practical Learning II
10
CREATING A COLUMN....................................................................................635 DELETING A COLUMN....................................................................................636 THE CELL TEMPLATE OF A COLUMN....................................................................637 THE NAME OF A COLUMN...............................................................................642 THE CAPTION OF A COLUMN............................................................................643 THE WIDTH OF A COLUMN..............................................................................645 REFERRING TO A COLUMN...............................................................................646 INTRODUCTION TO ROWS................................................................................647 THE ROWS OF A DATA GRID VIEW....................................................................648 THE HEIGHT OF A ROW.................................................................................650 INTRODUCTION...........................................................................................650 THE CELLS OF A ROW...................................................................................651 THE VALUE OF A CELL...................................................................................652 CREATING A RECORD....................................................................................655 WINDOWS CONTROL: THE GROUP BOX...................................................657 DESCRIPTION.............................................................................................657 GROUP BOX CREATION..................................................................................658 THE CAPTION OF A GROUP BOX.......................................................................659 THE GROUP BOX AS A CONTAINER.....................................................................659 AUTOMATICALLY RESIZING A GROUP BOX.............................................................660 GIVING FOCUS TO A GROUP BOX......................................................................661 USING A MNEMONIC.....................................................................................661 WINDOWS CONTROL: THE LIST VIEW.....................................................662 INTRODUCTION...........................................................................................662 LIST VIEW CREATION...................................................................................662 VISUALLY CREATING THE ITEMS OF A LIST VIEW...................................664 THE MAIN ITEMS OF THE LIST VIEW..................................................................664 VIEW STYLES.............................................................................................666 LIST VIEW ITEMS AND THEIR ICONS...................................................................670 THE COLUMNS OF A LIST VIEW...............................................................678 INTRODUCTION...........................................................................................678 VISUALLY CREATING COLUMNS.........................................................................678 PROGRAMMATICALLY CREATING COLUMNS.............................................................679 COLUMN INSERTION.....................................................................................683 THE NUMBER OF COLUMNS OF A LIST VIEW..........................................................685 LOCATING COLUMNS.....................................................................................685 DELETING COLUMNS.....................................................................................686 THE ITEMS OF A LIST VIEW.....................................................................686 ADDING ADDING
AN AN
ITEM TO THE LIST VIEW .................................................................686 ARRAY OF ITEMS...........................................................................691
USING A LIST VIEW................................................................................692 SELECTING AN ITEM FROM THE LIST VIEW ..........................................................692 EDITING A LABEL........................................................................................693 ACTIVATING AN ITEM....................................................................................694 USING COLUMNS.........................................................................................695 IDENTIFYING AN ITEM...................................................................................696 THE SUB ITEMS OF AN ITEM....................................................................696 INTRODUCTION ..........................................................................................696 VISUALLY CREATING SUB ITEMS.......................................................................697 PROGRAMMATICALLY CREATING SUB ITEMS...........................................................700
C# 3.0 Practical Learning II
11
MANAGING SUB ITEMS..................................................................................709 MANAGING THE ITEMS OF A LIST VIEW..................................................711 THE FONT, TEXT COLOR, AND BACKGROUND OF AN ITEM...........................................711 LOCATING A LIST VIEW ITEM..........................................................................714 DELETING ITEMS.........................................................................................715 CHARACTERISTICS OF A LIST VIEW........................................................715 COLUMN HEADER STYLE.................................................................................716 SELECTING ITEMS IN A LIST VIEW.....................................................................717 FULL ROW SELECTION...................................................................................718 GRID LINES..............................................................................................718 LIST ITEMS AND CHECK BOXES........................................................................719 THE OPEN DIALOG BOX...........................................................................719 DESCRIPTION.............................................................................................719 OPEN FILE DIALOG BOX CREATION...................................................................720 CHARACTERISTICS OF THE OPEN DIALOG BOX.......................................721 THE FILENAME ...........................................................................................721 THE FILTER ..............................................................................................721 THE FILTER INDEX ......................................................................................722 SHOWING THE DIALOG BOX ...........................................................................722 OPENING VARIOUS FILES ..............................................................................722 OPENING A FILE AS READ-ONLY .....................................................................723 PRINT PREVIEW......................................................................................724 INTRODUCTION...........................................................................................724 PROVIDING PRINT PREVIEW............................................................................724 CHARACTERISTICS OF THE PRINT PREVIEW...........................................726 THE PREVIEW AREA.....................................................................................726 PRINTING FROM THE PRINT PREVIEW.................................................................729 ZOOMING THE PREVIEW.................................................................................730 A DOCUMENT OF VARIOUS PAGES.....................................................................730 WINDOWS CONTROL: SCROLL BARS........................................................731 DESCRIPTION ............................................................................................731 AUTOMATICALLY-ADDED SCROLL BARS................................................................732 SCROLL BARS UPON REQUEST..........................................................................733 TEXT-BASED APPLICATIONS AND SCROLL BARS......................................................734 INTRODUCTION...........................................................................................735 CREATING A SCROLL BAR CONTROL....................................................................735 THE MINIMUM AND MAXIMUM..........................................................................736 THE VALUE OF A SCROLL BAR..........................................................................736 THE SMALL CHANGE.....................................................................................737 THE LARGE CHANGE.....................................................................................737 WINDOWS CONTROL: THE SCROLL BARS................................................737 INTRODUCTION ..........................................................................................738 CREATING A SCROLL BAR CONTROL....................................................................738 THE MINIMUM AND MAXIMUM..........................................................................738 THE VALUE OF A SCROLL BAR..........................................................................739 THE SMALL CHANGE.....................................................................................740 THE LARGE CHANGE.....................................................................................740 WINDOWS CONTROL: THE TICK COUNTER..............................................740
C# 3.0 Practical Learning II
12
INTRODUCTION...........................................................................................740 WINDOWS CONTROL: CHECKED LIST BOXES...........................................744 DESCRIPTION.............................................................................................744 CREATING A CHECKED LIST BOX.......................................................................747 CHARACTERISTICS OF A CHECKED LIST BOX...........................................750 INTRODUCTION...........................................................................................750 CREATING THE LIST OF ITEMS..........................................................................751 CHECKING AN ITEM......................................................................................752 AUTOMATICALLY CHECKING AN ITEM WHEN CLICKED................................................760 3-D CHECKED ITEMS...................................................................................761 WINDOWS CONTROL: THE DATE PICKER CONTROL.................................761 INTRODUCTION TO THE DATE PICKER CONTROL.......................................................761 CREATING A DATE/TIME PICKER......................................................................762 INTRODUCTION TO THE DATE PICKER..................................................................762 CHARACTERISTICS OF THE DATE PICKER................................................763 THE SPIN BUTTON.......................................................................................763 THE CHECK BOX ........................................................................................763 USING THE DATE PICKER ..............................................................................764 THE CALENDAR VISUAL CHARACTERISTICS ...........................................................765 THE ALIGNMENT OF THE CALENDAR ...................................................................766 THE MINIMUM AND THE MAXIMUM DATES ...........................................................766 THE VALUE OF THE CALENDAR .........................................................................766 THE CUSTOM FORMAT OF THE CALENDAR .............................................................766 WINDOWS CONTROLS: AN IMAGE LIST...................................................768 INTRODUCTION...........................................................................................768 CREATING AN IMAGE LIST..............................................................................769 THE SIZE OF THE IMAGES...............................................................................770 THE COLOR DEPTH......................................................................................773 CREATING THE COLLECTION OF IMAGES................................................................773 USING AN IMAGE LIST..................................................................................776 THE TRANSPARENT COLOR..............................................................................778 WINDOWS CONTROL: MASKED TEXT BOX................................................778 INTRODUCTION...........................................................................................778 MASKEDIT CHARACTERISTICS...........................................................................778 THE PAGE SETUP DIALOG BOX................................................................782 INTRODUCTION...........................................................................................782 CHARACTERISTICS OF THE PAGE SETUP DIALOG BOX................................................783 WINDOWS CONTROL: THE PROGRESS BAR..............................................785 DESCRIPTION.............................................................................................785 CREATING A PROGRESS BAR............................................................................785 CHARACTERISTICS OF A PROGRESS BAR.................................................786 INTRODUCTION...........................................................................................786 THE MINIMUM AND MAXIMUM..........................................................................787 THE VALUE OF A PROGRESS BAR......................................................................787 THE STEP VALUE OF A PROGRESS BAR................................................................789 THE STYLE OF A PROGRESS BAR.......................................................................790 WINDOWS CONTROL: THE SPLIT CONTAINER.........................................791
C# 3.0 Practical Learning II
13
INTRODUCTION...........................................................................................791 CREATING A SPLITTER...................................................................................792 INTRODUCTION...........................................................................................794 THE BACKGROUND OF A SPLIT CONTAINER............................................................794 THE SIZE OF THE SPLITTER.............................................................................794 THE ORIENTATION OF THE SPLITTER...................................................................795 MOVING THE SPLITTER..................................................................................795 THE SPLITTER INCREMENT..............................................................................795 FIXING A PANEL.........................................................................................795 WINDOWS CONTROL: THE TIMER............................................................796 INTRODUCTION...........................................................................................796 CHARACTERISTICS OF A TIMER..........................................................................798 WINDOWS CONTROL: THE TREE VIEW....................................................806 INTRODUCTION...........................................................................................806 TREE VIEW CREATION...................................................................................807 INTRODUCTION TO CREATING TREE VIEW NODES..................................813 VISUALLY CREATING NODES............................................................................813 PROGRAMMATICALLY CREATING NODES................................................................814 A NODE AND ITS CHILDREN....................................................................818 INTRODUCTION...........................................................................................818 CREATING CHILD NODES................................................................................821 THE NUMBER OF CHILD NODES........................................................................830 THE NODES OF A NODE.................................................................................831 NODE SELECTION........................................................................................831 NODE EDITION...........................................................................................832 NODE LOCATION.........................................................................................833 DELETING NODES........................................................................................847 CHARACTERISTICS OF A TREE VIEW.......................................................848 THE PATH TO A NODE...................................................................................848 HOT TRACKING...........................................................................................848 THE INTERMEDIARY LINES OF RELATED NODES.......................................................849 THE ROOT LINES........................................................................................850 NODE INDENTATION.....................................................................................850 FULL ROW SELECTION...................................................................................851 HIDING SELECTION AFTER LOSING FOCUS............................................................852 THE + AND - BUTTONS.................................................................................852 EXPANDING AND COLLAPSING TREE NODES...........................................................852 TREE NODES AND CHECK BOXES.......................................................................853 TREE NODES AND ICONS................................................................................854 WINDOWS CONTROLS: THE COLOR DIALOG BOX....................................863 INTRODUCTION...........................................................................................863 MAKING A COLOR DIALOG BOX AVAILABLE...........................................................865 THE COLOR PRODUCED BY A COLOR DIALOG BOX...................................................865 THE FULL VIEW OF A COLOR DIALOG BOX...........................................................866 SETTING THE COLOR OF, OR PAINTING, A PIXEL.....................................................867 GETTING THE COLOR OF A PIXEL.......................................................................869 WINDOWS CONTROL: THE DOMAIN UP-DOWN........................................869 DESCRIPTION.............................................................................................869 CREATING A DOMAIN UP-DOWN CONTROL...........................................................870 CHARACTERISTICS OF THE NUMERIC UP-DOWN CONTROL.....................871
C# 3.0 Practical Learning II
14
THE UP-DOWN ALIGNMENT............................................................................871 INTERCEPTING THE ARROW KEYS.......................................................................872 THE MINIMUM AND THE MAXIMUM VALUES...........................................................872 THE VALUE OF THE CONTROL...........................................................................873 THE TYPE OF VALUE.....................................................................................873 DISPLAYING DECIMAL NUMBERS.......................................................................873 THE THOUSAND SEPARATOR............................................................................873 THE INCREMENTING VALUE.............................................................................874 Applications:....................................................................................874 WINDOWS CONTROL: THE LABEL............................................................875 DESCRIPTION.............................................................................................875 CREATING A LABEL.......................................................................................875 THE CAPTION.............................................................................................876 AUTOMATICALLY SIZING A LABEL......................................................................878 CONTENT ALIGNMENT....................................................................................879 PICTURES ON A LABEL...................................................................................880 A LABEL'S MNEMONIC..................................................................................880 APPLICATION MENUS: THE MAIN MENU..................................................887 INTRODUCTION...........................................................................................887 MAIN MENU CREATION.................................................................................888 MENU CATEGORIES......................................................................................889 INTRODUCTION TO MENU ITEMS........................................................................892 ASSOCIATING MENU ITEMS TO MENU CATEGORIES...................................................894 ASSOCIATING MENU CATEGORIES TO THE MAIN MENU .............................................897 CODING A MENU ITEM..................................................................................905 WINDOWS CONTROL: THE PANEL CONTROL............................................906 INTRODUCTION...........................................................................................906 CREATING A PANEL......................................................................................907 CHARACTERISTICS OF A PANEL..........................................................................908 WINDOWS CONTROL: THE RADIO BUTTONS............................................909 DESCRIPTION.............................................................................................909 CREATING RADIO BUTTONS.............................................................................910 THE LOCATION OF A RADIO BUTTON..................................................................910 THE CAPTION OF A RADIO BUTTON....................................................................911 CHECKING A RADIO BUTTON............................................................................912 THE ALIGNMENT OF A RADIO BUTTON.................................................................913 THE APPEARANCE OF A RADIO BUTTON...............................................................914 Applications: ...................................................................................917 TAB CONTROLS AND TAB PAGES..............................................................917 DESCRIPTION.............................................................................................917 TAB CONTROL CREATION................................................................................920 THE TAB PAGES OF A TAB CONTROL........................................................921 INTRODUCTION...........................................................................................921 CREATING A TAB PAGE..................................................................................921 REMOVING A TAB PAGE.................................................................................927 TAB CONTROL AND TAB PAGE SELECTION...............................................927 TAB CONTROL SELECTION...............................................................................927 TAB PAGE SELECTION...................................................................................928 THE TAB OF A TAB PAGE..........................................................................930
C# 3.0 Practical Learning II
15
INTRODUCTION...........................................................................................930 THE CAPTION OF A TAB.................................................................................930 HOT TRACKING THE CAPTION OF A TAB PAGE........................................................933 PADDING THE CAPTION OF A TAB PAGE...............................................................933 THE TOOL TIP OF A TAB PAGE........................................................................934 A PICTURE ON A TAB...................................................................................934 MANAGING THE TABS..............................................................................936 THE NAVIGATION ARROWS OF A TAB CONTROL......................................................937 A TAB CONTROL WITH MULTI-LINE..................................................................937 THE SIZE MODE.........................................................................................938 THE TABS SIZE..........................................................................................940 THE ALIGNMENT OF TABS...............................................................................940 THE APPEARANCE OF THE TABS.........................................................................942 WINDOWS CONTROL: THE TIMER............................................................943 INTRODUCTION...........................................................................................943 CHARACTERISTICS OF A TIMER..........................................................................945 THE FORMS OF AN APPLICATION: INTRODUCTION.................................953 INTRODUCTION...........................................................................................953 FORM CREATION.........................................................................................954 THE NAME OF A FORM..................................................................................955 THE FORMS OF AN APPLICATION: THE TITLE BAR........................................................................................956 THE SYSTEM ICON.......................................................................................956 THE FORM'S CAPTION...................................................................................958 THE SYSTEM BUTTONS..................................................................................959 THE FORMS OF AN APPLICATION: THE FORM'S POSITION............................................................................962 THE THE THE THE
FORM'S LOCATION..................................................................................962 STARTUP POSITION OF A FORM...................................................................965 WINDOW STATE OF A FORM......................................................................966 FORM'S TASKBAR PRESENCE......................................................................967
THE FORMS OF AN APPLICATION: THE FORM'S MEASURES...........................................................................968 THE FORM'S SIZE.......................................................................................968 THE FORM BORDERS.....................................................................................971 THE FORMS OF AN APPLICATION: THE CLIENT AREA OF A FORM..................................................................973 INTRODUCTION...........................................................................................973 THE BACKGROUND COLOR OF A FORM.................................................................975 THE FORMS OF AN APPLICATION: THE BACKGROUND IMAGE OF A FORM.....................................................976 INTRODUCTION...........................................................................................976 BACKGROUND IMAGE OPTIONS.........................................................................978 FORM CREATION.........................................................................................983 FORM ACTIVATION.......................................................................................983 FORM DEACTIVATION....................................................................................983 FORM CLOSURE...........................................................................................984 DIALOG BOXES........................................................................................984
C# 3.0 Practical Learning II
16
DESCRIPTION.............................................................................................984 DIALOG BOX CREATION.................................................................................986 CHARACTERISTICS OF DIALOG BOXES....................................................987 THE BORDER STYLE OF A DIALOG BOX...............................................................987 THE MINIMIZE AND MAXIMIZE BOXES.................................................................988 CLOSING A DIALOG BOX................................................................................990 ACCEPTING AN ACTION..................................................................................990 CANCELLING AN ACTION.................................................................................990 THE HELP BUTTON......................................................................................991 MODAL AND MODELESS DIALOG BOXES..................................................992 MODAL DIALOG BOXES..................................................................................992 MODELESS DIALOG BOXES..............................................................................993 AN APPLICATION WITH VARIOUS FORMS OR DIALOG BOXES.......................................995 MESSAGE BOXES.....................................................................................997 INTRODUCTION...........................................................................................998 THE RETURN VALUE OF A MESSAGE BOX.............................................................998 THE MESSAGE OF A MESSAGE BOX....................................................................999 THE CAPTION OF A MESSAGE BOX.....................................................................999 THE BUTTONS OF A MESSAGE BOX...................................................................1000 THE ICON OF A MESSAGE BOX.......................................................................1001 THE DEFAULT BUTTON OF A MESSAGE BOX.........................................................1002 THE CODE EDITOR.................................................................................1004 INTRODUCTION.........................................................................................1004 THE TABS BAR.........................................................................................1006 THE TYPES COMBO BOX..............................................................................1008 THE MEMBERS COMBO BOX..........................................................................1008 CODE COLORS..........................................................................................1010 REGIONS................................................................................................1010 METHODS AND EVENTS OF WINDOWS CONTROLS.................................1013 INTRODUCTION.........................................................................................1013 CONTROL'S CONSTRUCTION AND DESTRUCTION.....................................................1013 CONTROL'S VISIBILITY................................................................................1015 CONTROL'S FOCUS.....................................................................................1016 THE Z-ORDER OF CONTROLS.........................................................................1017 CREATING NEW METHODS............................................................................1018 INTRODUCTION.........................................................................................1019 MICROSOFT VISUAL BASIC FUNCTIONS..............................................................1019 USING A LIBRARY......................................................................................1019 USING A VISUAL C++/CLI LIBRARY.............................................................1020 USING THE WIN32 LIBRARY........................................................................1020 A REVIEW OF DELEGATES......................................................................1022 INTRODUCTION.........................................................................................1022 DECLARING A DELEGATE...............................................................................1022 DELEGATES AND CLASSES..............................................................................1025 DELEGATES COMPOSITIONS............................................................................1026 A DELEGATE THAT TAKES ONE OF MORE ARGUMENTS............................................1026 A DELEGATE PASSED AS ARGUMENT.................................................................1027 APPLICATION ONLINE HELP..................................................................1029 INTRODUCTION.........................................................................................1029 STATUS BAR MESSAGES...............................................................................1034
C# 3.0 Practical Learning II
17
TOOL TIPS..............................................................................................1037 ONLINE HELP........................................................................................1039 INTRODUCTION.........................................................................................1039 THE HELP PROVIDER..................................................................................1044 INTRODUCTION TO HTML HELP.....................................................................1048 HTML HELP AND VISUAL STUDIO 2005APPLICATIONS.........................................1069 THE TOOLBOX........................................................................................1072 INTRODUCTION.........................................................................................1072 THE TOOLBOX AND ADDITIONAL CONTROLS.........................................................1073 THE SECTIONS OF THE TOOLBOX.....................................................................1075 THE LAYOUT OF A CATEGORY.........................................................................1076 ARRANGEMENT OF ITEMS IN THE TOOLBOX..........................................................1078 INTRODUCTION TO APPLICATION DESIGN............................................1078 INTRODUCTION ........................................................................................1079 COPYING A CONTROL .................................................................................1081 DYNAMIC CONTROL CREATION..............................................................1082 INTRODUCTION.........................................................................................1082 INITIALIZING THE COMPONENTS......................................................................1084 USING A PARTIAL CLASS..............................................................................1085 COMPONENTS TRACKING ON AN APPLICATION.......................................................1086 CONTROL DERIVATION.................................................................................1086 CONTROL SELECTION............................................................................1088 INTRODUCTION.........................................................................................1088 SINGLE CONTROL SELECTION.........................................................................1088 MULTIPLE CONTROL SELECTION......................................................................1089 CONTROL DELETION....................................................................................1090 THE PROPERTIES WINDOW...................................................................1090 INTRODUCTION.........................................................................................1090 DESCRIPTION...........................................................................................1091 ACCESSING THE PROPERTIES OF ONE OR MORE CONTROLS.......................................1092 PROPERTIES CATEGORIES.....................................................................1094 INTRODUCTION.........................................................................................1094 EMPTY FIELDS..........................................................................................1095 TEXT FIELDS............................................................................................1096 NUMERIC FIELDS.......................................................................................1097 DATE-BASED FIELDS..................................................................................1099 EXPANDABLE FIELDS...................................................................................1100 BOOLEAN FIELDS.......................................................................................1102 ACTION FIELDS.........................................................................................1102 LIST-BASED FIELDS...................................................................................1103 AREA-SELECTION FIELDS.............................................................................1104
C# 3.0 Practical Learning II
18
C# 3.0 Practical Learning II
19
Querying a List The Language Integrated Query Introduction to Querying When using for or foreach loops on a list, you get the value or a range of values inside of the loop. Once you exit the loop, the operation ends and you cannot access the value(s) that was(were) isolated. If you want to get the isolated value or an isolated list of values again, you would have to perform the operation (create the loop), again. In some cases, you may want to prepare and get one value, a few values, or a range of values for later use, or to use over and over again. To do this, you would create a value or a list of values and store that list in a variable, outside of any loop, then use the value or the list of values when needed. As applied to the for or the foreach loop, to perform this operation, you use a conditional statement that would examine the list, look for the value(s), get that value or those values that respond(s) to the condition. Any value(s) that respond(s) to the condition is(are) then stored in the new list. This technique of examining an array is referred to as querying.
Introduction to LINQ To support the ability to query a list, you can use the Language Integrated Query, abbreviated LINQ. To use LINQ in your application, you must include the System.Core.dll assembly in your program. If you started your application as an empty project: •
On the main menu, you can click Project -> Add Reference...
•
In the Solution Explorer, you can right-click the name of the project and click Add Reference...
•
In the Class View, you can right-click the name of the project and click Add Reference...
In the .NET tab of the Add Reference dialog box, you can click System.Core
C# 3.0 Practical Learning II
20
Then click OK. You must then use the System.Linq namespace in your code or you should include the using System.Linq; line in your list of namespaces. If you create an application by selecting the Console Application option from the New Project dialog box, the studio would add the necessary assembly to your project and the necessary namespace to your code file.
Selecting the Values To query a list, you write a statement using words and operators of the LINQ. If you have already used another query language, such as SQL, you may be wondering about LINQ's case-sensitivity. Here is the difference. Because the LINQ statements are written directly in the same sections with the langue of your code, LINQ's case-sensitivity depends on that language. For example, if you write your LINQ statement in a C# application as we will do here or in a C++ application where the language is case-sensitive, the LINQ's statement is case-sensitive and must be in lowercase. If you write the statement in a case-insensitive language such as Visual Basic or Pascal (such as CodeGear Delphi), you can write the statement with the case of your choice.
C# 3.0 Practical Learning II
21
The most fundamental operation you can perform on LINQ consists of creating, also referred to as selecting, a list of values, from an existing list such as an array. The basic formula to use is: var SubListName = from ValueHolder in List select ValueHolder;
The var keyword, the assignment operator "=", the from keyword, the in keyword, the select keyword, and the semicolon are required. The SubListName is a name of a new variable that will hold the list of values produced by this operation. The ValueHolder is the name of a variable that will be used to identify each resulting member of this operation. This variable will be equivalent to getting each member of the array that responds to a condition. The List factor represents the name of the variable that you would have created already. The List can be an array. Here is an example: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04 }; var Number = from n in Numbers select n; foreach(var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
This would produce: Number: 12.44 Number: 525.38 Number: 6.28 Number: 2448.32 Number: 632.04 Press any key to continue . . .
To make the code easier to read, you can spread the select statement to various lines. Here is an example: using System; using System.Linq;
C# 3.0 Practical Learning II
22
public class Exercise { static int Main(string[] args) { var Numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04 }; var Number = from n in Numbers select n; foreach(var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
Using a Collection-Based Variable We mentioned that the List factor of our formula could be an array. It can also be a collection-based variable; that is, a variable created from a collection-based class. The collection class you use must implement the IEnumerable generic interface. If you want, you can create your own class that implements this interface but the .NET Framework provides a complete set of classes that should suit every need. One of the built-in generic classes of the .NET Framework is called List and you can easily use it to create a list of values. Here is an example: using System; using System.Collections.Generic; public class Exercise { static int Main(string[] args) { var Numbers = new List<double>(); Numbers.Add(12.44); Numbers.Add(525.38); Numbers.Add(6.28); Numbers.Add(2448.32); Numbers.Add(632.04); }
return 0;
}
After creating the collection, you can use the same LINQ formula we saw for an array. Here is an example: using System; using System.Linq;
C# 3.0 Practical Learning II
23
using System.Collections.Generic; public class Exercise { static int Main(string[] args) { var Numbers = new List<double>(); Numbers.Add(12.44); Numbers.Add(525.38); Numbers.Add(6.28); Numbers.Add(2448.32); Numbers.Add(632.04); var Number = from n in Numbers select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); }
return 0;
}
This would produce the same result as seen earlier. Notice that, as always, the var keyword does not indicate the type of variable it is dealing with.
Using a Criterion to Create a Sub-List As you can see, simply using a select statement as done above produces the same list of values in the array. A criterion is a condition applied to a set of values to find out which one(s) respond(s) to the condition or validate the condition. When applied to an array, a criterion examines each member of the array, finds out what member responds to it, if so, adds that member to the from list. To apply a criterion, you create Boolean operation between the in statement and the select statement. This criterion is actually formulated using the where operator. The formula to use is: var SubListName = from ValueHolder in List where Condition select ValueHolder;
In the new section, the where keyword is required. The Condition is formulated using the logical operators we studied in Lesson 9. It can be in the form of: •
ValueHolder == SomeValue: If ValueHolder is the same as SomeValue, the list member that is being examined is valid
C# 3.0 Practical Learning II
24
•
ValueHolder < SomeValue: If ValueHolder is less than SomeValue, the list member that is being examined is valid
•
ValueHolder <= SomeValue: If ValueHolder is the same as, or lower than, SomeValue, the list member that is being examined is valid
•
ValueHolder > SomeValue: If ValueHolder is greater than SomeValue, the list member that is being examined is valid
•
ValueHolder >= SomeValue: If ValueHolder is the same as, or greater than, SomeValue, the list member that is being examined is valid
•
ValueHolder != SomeValue: If ValueHolder is different from SomeValue, the list member that is being examined is valid
•
!(ValueHolder == SomeValue): If ValueHolder is different from SomeValue, the list member that is being examined is valid
Remember that you must create the criterion as a Boolean operation. After applying the select statement, you can then use it as you see fit. For example, you can display its result(s) to the console. Here is an example: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where n == 327 select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
This would produce: Number: 327 Press any key to continue . . .
Of course, the purpose of querying a list is to isolate one or more values. As such, you can create an expression that checks a value and applies some condition to it. For example, in this list of C# 3.0 Practical Learning II
25
numbers, you may want to find out whether it contains one or more numbers that are divisible by 5. This operation can be carried by the % operator as in "number % 5"; but number % 5 is pure algebra, not Boolean. Therefore, you must add a condition to make it a valid Boolean expression. For example, you can find out if the number % 5 operation is equal to 0. Here is an example: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where n % 5 == 0 select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
This would produce: Number: 525 Press any key to continue . . .
To make the statement easier to read and less confusing, you should make it a habit to isolate the groups of statements in parentheses: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where (n % 5) == 0 select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member);
C# 3.0 Practical Learning II
26
}
return 0;
}
The above condition produced only one value because of the way the values exist in our array. A querying operation can also produce more than one value. Here is an example: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where n % 2 == 0 select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
This would produce: Number: 102 Number: 44 Number: 38 Number: 6 Number: 28 Number: 632 Number: 104 Press any key to continue . . .
Notice that the list includes only even numbers (those that are divisible by 2).
Operations on Queries Using Logical Conjunctions and Disjunctions In Lesson 10, we saw that you could use logical conjunctions and disjunctions to combine two or more Boolean expressions. These also are available in LINQ. To do this, use the where statement to C# 3.0 Practical Learning II
27
create the expression as you see fit. Here is an expression that uses a logical disjunction (&&) operation: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where n % 2 == 0 && n <= 100 select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
This would produce: Number: 44 Number: 38 Number: 6 Number: 28 Press any key to continue . . .
Once again, remember that the use of parentheses makes it easier to read the code and better understand it: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where (n % 2 == 0) && (n <= 100) select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
C# 3.0 Practical Learning II
28
}
Or better yet: using System; using System.Linq; public class Exercise { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where ((n % 2) == 0) && (n <= 100) select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); }
return 0;
}
Arranging the List When you create a list, you add the items in any order of your choice. For example, if you register the students of a school, you enter their information as it becomes available. In the same way, when you create a select statement, the items are added to its list in the order they appear in the main list. When treating the new list or when displaying it to the user, you may want to arrange it in alphabetical, numerical, or in chronological order. To support this operation, the LINQ provides the orderdy operator. To apply it, write the operator before the select operation followed by the from list. Here is an example: using System; using System.Linq; public class Program { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers orderby n select n;
C# 3.0 Practical Learning II
29
foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
This would produce: Number: 6 Number: 28 Number: 38 Number: 44 Number: 102 Number: 104 Number: 327 Number: 525 Number: 632 Number: 24481 Press any key to continue . . .
If you apply the orderby operator simply followed by a variable, the list is ordered alphabetically or numerically depending on the types of values in the list. This is referred to as ascending. To re-enforce this, you can follow the variable with the ascending keyword. Here is an example: using System; using System.Linq; public class Program { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers orderby n ascending select n;
}
foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0;
}
To arrange the list in reverse order, you can follow the variable name with the descending keyword. Here is an example: using System; using System.Linq; public class Program { static int Main(string[] args)
C# 3.0 Practical Learning II
30
{ var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers orderby n descending select n;
}
foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0;
}
This would produce: Number: 24481 Number: 632 Number: 525 Number: 327 Number: 104 Number: 102 Number: 44 Number: 38 Number: 28 Number: 6 Press any key to continue . . .
You can apply a where condition to the statement to select just a few values. For example, to get a list of odd numbers arranged in numerical order, you would write the statement as follows: using System; using System.Linq; public class Program { static int Main(string[] args) { var Numbers = new[] { 102, 44, 525, 38, 6, 28, 24481, 327, 632, 104 }; var Number = from n in Numbers where n % 2 != 0 orderby n ascending select n; foreach (var member in Number) Console.WriteLine("Number: {0}", member); return 0; }
}
C# 3.0 Practical Learning II
31
Influencing a LINQ Statement Using the Primitive Types From what we have learned so far, the type of list produced by a LINQ statement is primarily based on one of the data types we reviewed in Lesson 2 and in Lesson 3 (integers, double-precision numbers, strings, and date/time values). In Lesson 17, we saw that the integer and numeric types are in fact structures of the .NET Framework. As such, they are equipped with properties and methods. In your LINQ statement, you can explore the characteristics of those data types as you see fit.
Using the String Class If you create a string-based collection, you can use the properties and methods of the String class to refine the list produced by your LINQ statement. To do this, in the list produced by the where statement, you can access any of the properties or you can call any desired method of the String class using the period operator. For example, to get a list of names that start with a certain letter, you can call the StartsWith() method as follows: using System; using System.Linq; public class Program { static int Main(string[] args) { var Name = new[] { "Hermine", "Patrick", "Hank", "Bertine", "Julius", "Thomas", "Jeannette", "Patricia", "Henriette", "Raul", "David", "Paulette" }; var Names = from n in Name where n.StartsWith("P") // orderby n ascending select n; foreach (var member in Names) Console.WriteLine("Name: {0}", member); return 0; }
}
C# 3.0 Practical Learning II
32
Or to get a list of names that end with a certain sub-string, you would call the String.EndsWith() method. Here is an example: using System; using System.Linq; public class Program { static int Main(string[] args) { var Name = new[] { "Hermine", "Patrick", "Hank", "Bertine", "Julius", "Thomas", "Jeannette", "Patricia", "Henriette", "Raul", "David", "Paulette" }; var Names = from n in Name where n.EndsWith("ette") // orderby n ascending select n; foreach (var member in Names) Console.WriteLine("Name: {0}", member); return 0; }
}
In the same ways, to create a list of names that contain a certain sub-string, you can call the String.Contains() method as follows: using System; using System.Linq; public class Program { static int Main(string[] args) { var Name = new[] { "Hermine", "Patrick", "Hank", "Bertine", "Julius", "Thomas", "Jeannette", "Patricia", "Henriette", "Raul", "David", "Paulette" }; var Names = from n in Name where n.Contains("au") // orderby n ascending select n;
}
foreach (var member in Names) Console.WriteLine("Name: {0}", member); return 0;
}
C# 3.0 Practical Learning II
33
LINQ and Classes Introduction To create more effective LINQ statements, you can use many of the features of the C# language we have studied in previous lessons. For example, instead of using one of the primitive types to create your list as we have done so far, you may want to use your own class. You can start by creating the class normally as you see fit. Here is an example: public class Person { public string FirstName; public string LastName; public char Gender;
}
public Person(string First, string Last, char Sex) { FirstName = First; LastName = Last; Gender = Sex; }
Obviously before considering the class in your LINQ statement, you should first create a collection variable that would hold its values. You can create the list as an array. Once the list is ready, when formulating your LINQ statement, use the from variable to access a member of the class using the period operator. Here is an example: using System; using System.Linq; public class Person { public string FirstName; public string LastName; public char Gender; public Person(string First, string Last, char Sex) { FirstName = First; LastName = Last; Gender = Sex; } } public class Program { static int Main(string[] args) {
C# 3.0 Practical Learning II
34
var People = new Person[] { new Person("Paulette", "Cranston", 'F'), new Person("Harry", "Kumar", 'M'), new Person("Jules", "Davidson", 'M'), new Person("Leslie", "Harrington", 'U'), new Person("Ernest", "Colson", 'M'), new Person("Patricia", "Katts", 'F'), new Person("Patrice", "Abanda", 'U'), new Person("Frank", "Thomasson", 'M') }; var Persons = from Pers in People select Pers.LastName; foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual); return 0; }
}
This would produce: Person Name: Cranston Person Name: Kumar Person Name: Davidson Person Name: Harrington Person Name: Colson Person Name: Katts Person Name: Abanda Person Name: Thomasson Press any key to continue . . .
In the same way, you can use any of the regular C# operators to produce any result of your choice. For example, when studying strings, we saw that you could use the + operator to combine strings. Here is an example: using System; using System.Linq; public class Person { public string FirstName; public string LastName; public char Gender; public Person(string First, string Last, char Sex) { FirstName = First; LastName = Last; Gender = Sex; } }
C# 3.0 Practical Learning II
35
public class Program { static int Main(string[] args) { var People = new Person[] { new Person("Paulette", "Cranston", 'F'), new Person("Harry", "Kumar", 'M'), new Person("Jules", "Davidson", 'M'), new Person("Leslie", "Harrington", 'U'), new Person("Ernest", "Colson", 'M'), new Person("Patricia", "Katts", 'F'), new Person("Patrice", "Abanda", 'U'), new Person("Frank", "Thomasson", 'M') }; var Persons = from Pers in People select Pers.LastName + ", " + Pers.FirstName;
}
foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual); return 0;
}
This would produce: Person Name: Cranston, Paulette Person Name: Kumar, Harry Person Name: Davidson, Jules Person Name: Harrington, Leslie Person Name: Colson, Ernest Person Name: Katts, Patricia Person Name: Abanda, Patrice Person Name: Thomasson, Frank Press any key to continue . . .
Remember that the essence of querying a list is to create a list of particular data based on a criterion, which is done by applying a where condition. Here is an example: public class Program { static int Main(string[] args) { var People = new Person[] { new Person("Paulette", "Cranston", 'F'), new Person("Harry", "Kumar", 'M'), new Person("Jules", "Davidson", 'M'), new Person("Leslie", "Harrington", 'U'), new Person("Ernest", "Colson", 'M'), new Person("Patricia", "Katts", 'F'), new Person("Patrice", "Abanda", 'U'),
C# 3.0 Practical Learning II
36
new Person("Frank", "Thomasson", 'M') }; var Persons = from Pers in People where Pers.Gender == 'F' select Pers.LastName + ", " + Pers.FirstName;
}
foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual); return 0;
}
This would produce: Person Name: Cranston, Paulette Person Name: Katts, Patricia Press any key to continue . . .
To perform a more particular operation on a class, you can create a method in it and then call that method in your LINQ statement. This means that, just as you can access a field or a property of the class, you can access any of its internal or public methods. Here is an example: using System; using System.Linq; public class Person { public string FirstName; public string LastName; public char Gender; public Person(string First, string Last, char Sex) { FirstName = First; LastName = Last; Gender = Sex; } internal string GetFullName() { return LastName + ", " + FirstName; } } public class Program { static int Main(string[] args) { var People = new Person[] { new Person("Paulette", "Cranston", 'F'),
C# 3.0 Practical Learning II
37
new new new new new new new
Person("Harry", "Kumar", 'M'), Person("Jules", "Davidson", 'M'), Person("Leslie", "Harrington", 'U'), Person("Ernest", "Colson", 'M'), Person("Patricia", "Katts", 'F'), Person("Patrice", "Abanda", 'U'), Person("Frank", "Thomasson", 'M')
}; var Persons = from Pers in People where Pers.Gender == 'M' select Pers.GetFullName(); foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual); return 0; }
}
This would produce: Person Name: Kumar, Harry Person Name: Davidson, Jules Person Name: Colson, Ernest Person Name: Thomasson, Frank Press any key to continue . . .
Using Built-In Classes There are two types of built-in classes you can use in your application when it comes to LINQ. You can use any of the nongeneric collection classes to create a list of values. The other category is the generic collection classes.
LINQ Operators Letting a Sub-List We saw that you can get the result of a LINQ statement from the select section. In reality, the select statement simply indicates that the result is ready and it hands it to the other parts of the program. Instead of getting the result directly from the select statement, you can first store it in a local LINQ variable. This allows you to treat the result as a variable that you can then manipulate before getting the final result.
C# 3.0 Practical Learning II
38
To create a local variable in the LINQ statement, you can use the let operator. You must use it before the select statement to hold the result. Here is an example: public class Program { static int Main(string[] args) { var Persons = from Pers in People let FullName = Pers.LastName + ", " + Pers.FirstName select FullName;
}
foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual); return 0;
}
If you need a where condition but your let variable would be used only to hold the final result, you can create that variable after the where statement. Here is an example: public class Program { static int Main(string[] args) { var Persons = from Pers in People where Pers.Gender == 'U' let FullName = Pers.LastName + ", " + Pers.FirstName select FullName; foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual); return 0; }
}
In this case, you can create the let variable before the where statement and you would get the same result: using System; using System.Linq; public class Person { public string FirstName; public string LastName; public char Gender; public Person(string First, string Last, char Sex) { FirstName = First;
C# 3.0 Practical Learning II
39
}
LastName = Last; Gender = Sex;
} public class Program { static int Main(string[] args) { var People = new Person[] { new Person("Paulette", "Cranston", 'F'), new Person("Harry", "Kumar", 'M'), new Person("Jules", "Davidson", 'M'), new Person("Leslie", "Harrington", 'U'), new Person("Ernest", "Colson", 'M'), new Person("Patricia", "Katts", 'F'), new Person("Patrice", "Abanda", 'U'), new Person("Frank", "Thomasson", 'M') }; var Persons = from Pers in People let FullName = Pers.LastName + ", " + Pers.FirstName where Pers.Gender == 'U' select FullName; foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual); return 0; }
}
This would produce: Person Name: Harrington, Leslie Person Name: Abanda, Patrice Press any key to continue . . .
Creating a new List To get the final result of a query, you may want to combine a few fields or properties of each member of the result. For example, as we have seen so far, you may want to combine the last and the first name of each result to create a full name. Besides, or instead of, the let operator, you can use the new operator to create such a combination. To use the new operator, after the select keyword, type new followed by an opening and a closing curly brackets. Inside the brackets, create an expression as you see fit and assign it to a local variable C# 3.0 Practical Learning II
40
in the curly brackets. When accessing the result in your foreach loop, apply the period operator on the foreach variable to access the new local variable. Here is an example: public class Person { public string FirstName; public string LastName; public char Gender; public Person(string First, string Last, char Sex) { FirstName = First; LastName = Last; Gender = Sex; } } public class Program { static int Main(string[] args) { var People = new Person[] { new Person("Paulette", "Cranston", 'F'), new Person("Harry", "Kumar", 'M'), new Person("Jules", "Davidson", 'M'), new Person("Leslie", "Harrington", 'U'), new Person("Ernest", "Colson", 'M'), new Person("Patricia", "Katts", 'F'), new Person("Patrice", "Abanda", 'U'), new Person("Frank", "Thomasson", 'M') }; var Persons = from Pers in People select new {FullName=Pers.LastName+", "+Pers.FirstName }; foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual.FullName); return 0; } }
To make the statement easier to read, you can span it on various lines: public class Program { static int Main(string[] args) { var Persons = from Pers in People select new
C# 3.0 Practical Learning II
41
{
};
FullName = Pers.LastName + ", " + Pers.FirstName
foreach (var Individual in Persons) Console.WriteLine("Person Name: {0}", Individual.FullName); return 0; } }
C# 3.0 Practical Learning II
42
Exploring the LINQ The IEnumerable Generic Interface Introduction In our introduction to LINQ, we saw how to create a LINQ statement by declaring a variable using the var keyword. Here is an example: using System; using System.Linq; public class Program { static int Main(string[] args) { var People = new string[] { "Paulette Cranston", "Harry Kumar", "Jules Davidson", "Leslie Harrington", "Ernest Colson", "Patricia Katts", "Patrice Abanda", "Frank Thomasson" }; var Persons = from Pers in People select Pers; foreach (var Individual in Persons) Console.WriteLine("Person: {0}", Individual); return 0; }
}
This would produce: Person: Paulette Cranston Person: Harry Kumar
C# 3.0 Practical Learning II
43
Person: Jules Davidson Person: Leslie Harrington Person: Ernest Colson Person: Patricia Katts Person: Patrice Abanda Person: Frank Thomasson Press any key to continue . . .
From what we have learned so far, the only thing we know from this code is that it gives us a list and we can display the values of this list to the console. At times, we may want to get more information about some characteristics of the result, not simply its values. To assist you with exploring the characteristics of a LINQ statement, the .NET Framework provides the IEnumerable interface.
Using IEnumerable In all of the statements we have created/written so far, we used the var keyword, which allowed us to let the compiler figure out what type of value the statement would produce. In reality, a LINQ statement is an object of type IEnumerable. The IEnumerable object used in LINQ is an interface defined in the System.Collections.Generic namespace defined in the mscorlib.dll assembly. This also means that you want to use it, you should include the System.Collections.Generic namespace in your code file. Since a LINQ statement produces a list of type IEnumerable, instead of the var keyword, you can declare the statement using that. Inside the <> operator, enter the type of list that the collection variable contains. Here is an example: using System; using System.Linq; using System.Collections.Generic; public class Program { static int Main(string[] args) { var People = new string[] { "Paulette Cranston", "Harry Kumar", "Jules Davidson", "Leslie Harrington", "Ernest Colson", "Patricia Katts", "Patrice Abanda", "Frank Thomasson" };
C# 3.0 Practical Learning II
44
IEnumerable<string> Persons = from Pers in People select Pers;
}
foreach (var Individual in Persons) Console.WriteLine("Person: {0}", Individual); return 0;
}
This statement is the same as the previous except that the var keyword has been replaced with IEnumerable<string> and it will produce the same result we had earlier.
The Characteristics of IEnumerable As mentioned already, when you create a LINQ statement, it produces a list. Although the list is of type IEnumerable, since this is only an interface, the result relies on an actual class to provide its characteristics. The class that gives you information about a result is called Enumerable. The Enumerable class in defined in the System.Linq namespace that is part of the System.Core.dll assembly. It is actually the Enumerable class that implements the methods declared in the IEnumerable interface. Because the Enumerable class is extremely big, we cannot review all of its methods. We will use them as we move on and when a particular method becomes necessary. As mentioned already, a LINQ statement produces an Enumerable list. You can then use that result to access a method of the class. For example, the IEnumerable.Count() method is used to know the number of items in the resulting list. You can access it from the resulting list. Here is an example: using System; using System.Linq; using System.Collections.Generic; public class Program { static int Main(string[] args) { var People = new string[] { "Paulette Cranston", "Harry Kumar", "Jules Davidson", "Leslie Harrington", "Ernest Colson", "Patricia Katts", "Patrice Abanda",
C# 3.0 Practical Learning II
45
"Frank Thomasson" }; IEnumerable<string> Persons = from Pers in People select Pers; int Total = Persons.Count(); Console.Write("There are {0} people in the list and they are: ", Total); foreach (var Individual in Persons) Console.Write("{0}, ", Individual);
}
Console.WriteLine(); return 0;
}
This would produce: There are 8 people in the list and they are: Paulette Cranston, Harry Kumar, Jul es Davidson, Leslie Harrington, Ernest Colson, Patricia Katts, Patrice Abanda, F rank Thomasson, Press any key to continue . . .
Remember that you can still use the var keyword to declare the variable that would hold the resulting list. Since we have determined that the LINQ statement produces an Enumerable object, if you don't need the list itself, you can declare a variable that is the type returned by a method, put the statement in parentheses, and then access the method outside the closing parenthesis using the period operator. Here is an example: using System; using System.Linq; using System.Collections.Generic; public class Program { static int Main(string[] args) { var People = new string[] { "Paulette Cranston", "Harry Kumar", "Jules Davidson", "Leslie Harrington", "Ernest Colson", "Patricia Katts", "Patrice Abanda", "Frank Thomasson" };
C# 3.0 Practical Learning II
46
int Total = (from Pers in People select Pers).Count(); Total);
Console.Write("There are {0} people in the list.", Console.WriteLine(); return 0;
} } There are 8 people in the list. Press any key to continue . . .
Remember that the IEnumerable.Count() method returns the number of items in the result of the LINQ statement, not the number of items in the original list. The following examples illustrate it: using System; using System.Linq; public class Person { public string FirstName; public string LastName; public char Gender;
}
public Person(string First, string Last, char Sex) { FirstName = First; LastName = Last; Gender = Sex; }
public class Program { static int Main(string[] args) { var People = new Person[] { new Person("Paulette", "Cranston", 'F'), new Person("Harry", "Kumar", 'M'), new Person("Jules", "Davidson", 'M'), new Person("Leslie", "Harrington", 'U'), new Person("Ernest", "Colson", 'M'), new Person("Patricia", "Katts", 'F'), new Person("Patrice", "Abanda", 'U'), new Person("Frank", "Thomasson", 'M') }; var AllPeople = from Pers in People select Pers; int Men = (from Males
C# 3.0 Practical Learning II
47
in AllPeople where Males.Gender == 'M' select Males).Count(); int Women = (from Females in AllPeople where ((Females.Gender != 'M') && (Females.Gender != 'U')) select Females).Count(); Console.Write("The original list contains {0} people and they are: ", AllPeople.Count()); foreach (var Individual in AllPeople) Console.Write("{0}, ", Individual); Console.WriteLine(); Console.WriteLine("This list contains {0} men and {1} women.", }
Men, Women); return 0;
}
This would produce: The original list contains 8 people and they are: Person, Person, Person, Person , Person, Person, Person, Person, This list contains 4 men and 2 women. Press any key to continue . . .
C# 3.0 Practical Learning II
48
Introduction to XML The Extensible Markup Language Overview of Files Consider the following list: Employee First Name
Last Name Date Hired
Hourly Salary
Johnny
Watts
10/05/198 22.85 4
Patrick
Garçon
7/22/2000 14.50
Ernest
Simms
04/18/199 18.05 6
Gertrude Monay
8/06/2002 26.35
In Lesson 33, we saw how to create and save such a list. Here is an example of performing these operations:
using using using using
System; System.IO; System.Collections; System.Runtime.Serialization.Formatters.Binary;
[Serializable] public sealed class Employee { public string FirstName; public string LastName;
C# 3.0 Practical Learning II
49
public DateTime DateHired; public double HourlySalary;
}
public static class Program { static int Main(string[] args) { ArrayList lstEmployees = new ArrayList(); Employee contractor = null; contractor = new Employee(); contractor.FirstName = "Johnny"; contractor.LastName = "Watts"; contractor.DateHired = new DateTime(1984, 5, 10); contractor.HourlySalary = 22.85; lstEmployees.Add(contractor); contractor = new Employee(); contractor.FirstName = "Patrick"; contractor.LastName = "Garçon"; contractor.DateHired = new DateTime(2000, 7, 24); contractor.HourlySalary = 14.50; lstEmployees.Add(contractor); contractor = new Employee(); contractor.FirstName = "Ernest"; contractor.LastName = "Simms"; contractor.DateHired = new DateTime(1996, 4, 16); contractor.HourlySalary = 18.05; lstEmployees.Add(contractor); contractor = new Employee(); contractor.FirstName = "Gertrude"; contractor.LastName = "Monay"; contractor.DateHired = new DateTime(2002, 3, 8); contractor.HourlySalary = 26.35; lstEmployees.Add(contractor); FileStream fsEmployees = new FileStream("Employees.mpl", FileMode.Create, FileAccess.Write
);
BinaryFormatter bfEmployees = new BinaryFormatter(); bfEmployees.Serialize(fsEmployees, lstEmployees); fsEmployees.Close(); }
return 0;
}
When saving this file, we chose an extension (.mpl) at random. After saving the values to a file, at one time, you may want to retrieve the values from that list. Here is an example: using System;
C# 3.0 Practical Learning II
50
using System.IO; using System.Collections; using System.Runtime.Serialization.Formatters.Binary; [Serializable] public sealed class Employee { public string FirstName; public string LastName; public DateTime DateHired; public double HourlySalary; } public static class Program { static int Main(string[] args) { FileStream fsEmployees = new FileStream("Employees.mpl", FileMode.Open, FileAccess.Read) ; BinaryFormatter bfEmployees = new BinaryFormatter(); ArrayList contractors = (ArrayList)bfEmployees.Deserialize(fsEmployees); fsEmployees.Close(); Console.WriteLine("===================================== =");
Console.WriteLine("==== Employees Records ==============="); foreach (Employee empl in contractors) { Console.WriteLine("-------------------------------------"); Console.WriteLine("Employee Name: {0}, {1}", empl.LastName, empl.FirstName); Console.WriteLine("Date Hired: {0:D}", empl.DateHired); Console.WriteLine("Hourly Salary: {0:C}", empl.HourlySalary); } Console.WriteLine("===================================== =\n"); return 0; }
}
This would produce: ====================================== ==== Employees Records =============== -------------------------------------Employee Name: Watts, Johnny Date Hired: Thursday, May 10, 1984 Hourly Salary: $22.85
C# 3.0 Practical Learning II
51
-------------------------------------Employee Name: Garçon, Patrick Date Hired: Monday, July 24, 2000 Hourly Salary: $14.50 -------------------------------------Employee Name: Simms, Ernest Date Hired: Tuesday, April 16, 1996 Hourly Salary: $18.05 -------------------------------------Employee Name: Monay, Gertrude Date Hired: Friday, March 08, 2002 Hourly Salary: $26.35 ====================================== Press any key to continue . . .
When you create this type of file, you choose the programming environment of your choice and save the file. You cannot open that file in just any application. You must create and distribute the application to those who want to be able to open a file created by your application. It could be useful to create a type of file using any application of your choice and be able to open that file using another type of application that you may not even know.
Introduction to XML The Extensible Markup Language, or XML, is a technique of using a document, such as a text file, to describe information and make that information available to whatever and whoever can take advantage of it. The description is done so the document can be created by one person or company and used by another person or another company without having to know who first created the document. This is because the document thus created is not a program, it is not an application: it is just a text-based document. Because XML is very flexible, it can be used in regular Windows applications, in databases, in web-based systems (Internet), in communication applications, in computer networks, in scientific applications, etc. To make sure that XML can be universally used without one person or group owning it, it is standardized by the W3C (http://www.w3c.org) organization. XML is released through an XML Recommendation document with a version.
In this ebook, we will learn or use XML through the .NET Framework classes. The particularity is that these classes are highly structured to take care of all facets of XML without compromising the standards. In fact, the .NET Framework classes are highly conform to the W3C standards in all areas. To create an XML file, in the document, you type units of code using normal characters of the English language. The XML document is C# 3.0 Practical Learning II
52
made of units called entities. These entities are spread on various lines of the document as you judge them necessary and as we will learn. XML has strict rules as to how the contents of the document should or must be structured. After an XML document has been created and is available, in order to use it, you need a program that can read, analyze, and interpret it. This program is called a parser. The most popular parser used in Microsoft Windows applications is MSXML, published by Microsoft.
Markup A markup is an instruction that defines XML. The fundamental formula of a markup is:
The left angle bracket "<" and the right angle bracket ">" are required. Inside of these symbols, you type a word or a group of words of your choice, using regular characters of the English alphabet and sometimes non-readable characters such as ?, !, or [. The combination of a left angle bracket "<", the right angle bracket ">", and what is inside of these symbols is called a markup. There are various types of markups we will learn.
The Document Type Declaration (DTD) As mentioned above, XML is released as a version. Because there can be various versions, the first line that can be processed in an XML file must specify the version of XML you are using. At the time of this writing, the widely supported version of the .NET Framework is 1.0. When creating an XML file, you should (should in 1.0 but must in 1.1) specify what version your file is conform with, especially if you are using a version higher than 1.0. For this reason, an XML file should start (again, must, in 1.1), in the top section, with a line known as an XML declaration. It starts with . An example of such a line is:
By default, an XML file created using Visual Studio 2005 specifies the version as 1.0. Under the XML declaration line, you can then create the necessary tags of the XML file.
Encoding Declaration As mentioned already, the tags are created using characters of the alphabet and conform to the ISO standard. This is known as the
C# 3.0 Practical Learning II
53
encoding declaration. For example, most of the characters used in the US English language are known as ASCII. These characters use a combination of 7 bits to create a symbol (because the computer can only recognize 8 bits, the last bit is left for other uses). Such an encoding is specified as UTF-8. There are other standards such as UTF-16 (for wide, 2-Byte, characters). To specify the encoding you are using, type encoding followed by the encoding scheme you are using, which must be assigned as a string. The encoding is specified in the first line. Here is an example:
Creating an XML File Due to the high level of support of XML in the .NET Framework, there are various ways you can create an XML file. The most common technique consists of using a simple text editor. In Microsoft Windows, this would be Notepad. An XML file is first of all a normal text-based document that has a .xml extension. Therefore, however you create it, it must specify that extension. Many other applications allow creating an XML file or generating one from an existing file. There are also commercial editors you can get or purchase to create an XML file.
Practical Learning: Introducing XML 1. Start Microsoft Visual C# and create a Console Application named CollegeParkAutoParts1 2. To save the application, on the Standard toolbar, click the Save All button 3. Accept all defaults and click Save
Writing XML Code Introduction to the Document Object Model To implement XML, the .NET Framework provides the System.Xml namespace. When you create an XML file, there are standard rules you should (must) follow in order to have a valid document. The standards for an XML file are defined by the W3C Document Object Model (DOM). To support these standards, the System.Xml namespace provides the XmlDocument class. This class allows you to create an XML document, to populate it with the desired contents,
C# 3.0 Practical Learning II
54
and to perform many other related operations on the contents of the file.
Writing XML Code Using XmlDocument To create XML code using XmlDocument, this class has a method called LoadXml(). Its syntax is: public virtual void LoadXml(string xml);
This
method
takes a string as argument. The XmlDocument.LoadXml() method doesn't create an XML file, it only allows you to provide or create XML code. The code can be created as argument. You can also first declare and initialize a string variable with the XML code, then pass it as argument to the XmlDocument.LoadXml() method.
Practical Learning: Creating an XML Document 1. To start with XML, change the Program.cs file as follows: using System; using System.Xml; namespace CollegeParkAutoParts1 { class Program { static int Main(string[] args) { XmlDocument docXML = new XmlDocument(); docXML.LoadXml(""); return 0; }
}
}
2. Save the Program.cs file
Writing XML Code Using the Code Editor In the next sections, we will see how to create an XML file with the Add New Item dialog box. After creating the file and displaying it in the Code Editor, you can start editing it. The Code Editor is equipped to assist you with various options. Whenever you start typing, the editor would display one or more options to you. Here is an example:
C# 3.0 Practical Learning II
55
When different options are presented to you, you can press the arrow keys to select an option and press Enter. You can also use the mouse to click an option. When typing other XML items as we will learn, the Code Editor is equipped to work in concert with you.
Saving an XML File Introduction Probably the most common way to create an XML file in Microsoft Windows consists of using Notepad or any other text editor. After opening the text editor, you can enter the necessary lines of text. After creating the file, you must save it. When saving it, you can include the name of the file in double-quotes:
C# 3.0 Practical Learning II
56
You can also first set the Save As Type combo box to All Files and then enter the name of the file with the .xml extension.
Using the Wizard To assist you with creating XML Files, Microsoft Visual C# includes an XML File option in the Add New Item dialog box. After selecting this option, you can accept the suggested name of the file or replace it in the Name text box. If you don't specify the extension, the wizard would add it for you.
Practical Learning: Creating the Root Tag 1. On the main menu, click Project -> Add New Item... 2. In the Templates list, click XML File 3. Set the Name to Parts
4. Click Add
Saving a DOM Object If you call the XmlDocument.LoadXml() method, only the XML code is created, not the file. To actually create the Windows file, you can C# 3.0 Practical Learning II
57
call the XmlDocument.Save() method. This method is provided in four versions. One of the versions takes as argument a string value. The syntax of this method is: public virtual void Save(string filename);
The argument must be a valid filename and must include the .xml extension. If you pass a string without backlashes, the file would be created in the same folder as the current project. If you want the file to be created somewhere else (in a different directory), pass the whole path.
Opening an XML File Introduction Whether you created an XML file or someone else did, you can open it easily to view its contents. The easiest way to open an XML file is to use a text editor, such as Notepad. Because the Code Editor has a friendlier appearance and it is available to you, it is a better candidate. To open an XML file, on the main menu, you can click File -> Open File..., locate the file, and click Open.
An XML File in a Browser After creating an XML file, one way you can use it is to display it in a grid-based window such as a spreadsheet. Another way you can display an XML file is in a browser. To do this, if you see the file in Windows Explorer or in My Documents, you can double-click it. Here is an example:
C# 3.0 Practical Learning II
58
Using a Style Sheet to Display an XML File in a Browser When an XML file is displayed in a browser, it appears in a format that could be unclear. If you want the XML code to display as if it were HTML, you can create a cascading style sheet that would format the tags and display the text as you prefer. Here is an example: employee.css EmplNumber { display: block;
C# 3.0 Practical Learning II
59
font-weight: bold; font-size: 16pt;
color: white; Serif;
font-family: Garamond, Georgia, 'Times New Roman' ,
background-color: #990000; } FirstName { font-size: 10pt; font-family: Verdana, Tahoma, Arial, Sans-Serif; background-color: white; } LastName { font-size: 10pt; font-family: Verdana, Tahoma, Arial, Sans-Serif; background-color: white; } HourlySalary { font-size: 10pt; color: #ff0066; font-family: Verdana, Tahoma, Arial, Sans-Serif; background-color: white; display: block; }
Then, in the first line of the XML file, you can add a line such as the following:
Programmatically Opening an XML File Using the DOM At times, you will need to programmatically access an XML file. To support this operation, the XmlDocument class provides the Load() method which is available in various versions. One of the syntaxes used by this method is: public virtual void Load(string filename);
This version takes as argument the name or path of the file. Here is an example of calling it: using System; using System.Xml; namespace VideoCollection1 { class Program {
C# 3.0 Practical Learning II
60
static int Main(string[] args) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load("Videos.xml"); return 0; }
}
}
In this case, the compiler would look for the file in the (Release) folder of the current application. You can also provide a complete path to the file. Either way, if the compiler doesn't find the file, it would throw a FileNotFoundException exception. For this reason, it is cautious to first check that the file exists before opening it. This can be done as follows: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { XmlDocument xmlDoc = new XmlDocument(); string strFilename = "Videos123.xml";
located",
if (File.Exists(strFilename)) xmlDoc.Load(strFilename); else Console.WriteLine("The file {0} could not be strFilename);
} }
return 0;
}
An alternative is to handle the exception yourself. You can also use a Stream-based object to identify the file. Once the object is ready, you can use the following version of the Load() method to open it: public virtual void Load(Stream inStream);
This method expects a Stream type of object, such as a FileStream variable. Here is an example of calling it: using System;
C# 3.0 Practical Learning II
61
using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); FileStream fsVideos = null; if (File.Exists(strFilename)) { fsVideos = new FileStream(strFilename, FileMode.Open, FileAccess.Read
);
xmlDoc.Load(fsVideos); } else located",
Console.WriteLine("The file {0} could not be strFilename);
} }
return 0;
}
Programmatically Reading an XML File Many of the XML files you encounter will have been created by someone else. Still, because it is primarily a text document, you are expected to be able to read any XML file and figure out its content, or at least most of it. As mentioned already, you can open an XML file using a text editor such as Notepad. After opening the file, you can start by checking the document declaration, then move to other items. Another way you can explore an XML file consists of programmatically reading it. This is also referred to as parsing (the parser parses the document). To support reading an XML file, the .NET Framework provides the abstract XmlReader class as the ancestor of classes that can read an XML file. One of the classes derived from XmlReader is called XmlTextReader. The XmlTextReader class provides the ability to read the file from the left to the right sides and from the top to the bottom sections. This class has very important characteristics you must remember:
C# 3.0 Practical Learning II
62
•
This class proceeds with a forward only approach: it reads a character or a word, moves to the next, and cannot refer back. This means that, after it has visited an item and has moved ahead, you cannot use it to refer to an item back
•
This class is read-only: you cannot use it to edit or modify an item (but, when you get to an item, you can use another object to modify the item)
To programmatically read an XML file, you can start by declaring a variable of type XmlTextReader using one of its constructors, including the default. To specify the file you want to open and read, you can use the constructor whose syntax is the following : public XmlTextReader(string url);
When using this method, pass the name of the file or its path as argument. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; if (File.Exists(strFilename)) XmlTextReader rdrXml = new XmlTextReader(strFilename); else Console.WriteLine("The file {0} could not be located", strFilename);
} }
Console.WriteLine(); return 0;
}
You can also identify a file using a Stream-based object. Once the object is ready, you can pass it to the following constructor of the class: public XmlTextReader(Stream input);
Here is an example: using System; using System.IO;
C# 3.0 Practical Learning II
63
using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; FileStream fsVideos = new FileStream(strFilename, FileMode.Open, FileAccess.Read ); if (File.Exists(strFilename)) XmlTextReader rdrXml = new XmlTextReader(fsVideos ); else Console.WriteLine("The file {0} could not be located", strFilename); fsVideos.Close(); Console.WriteLine(); return 0; }
}
}
To actually read the file, the XmlTextReader is equipped with the Read() method whose syntax is: public override bool Read();
As you may suspect, this method only tells you that it successfully read an item. It doesn't tell you what it read. As stated already, the XmlTextReader scans a file in a left-right-top-down approach. When it has read something, it returns true. If it didn't or couldn't read something, it returns false. Therefore, you can call it to read an item. If it succeeds, it returns true. After reading that item, you can call it again to move to the next item. If there is a next item, it reads it and returns true. But, if there is no next item, the Read() method would not be able to read it and it would return false. In other words, you can ask the Read() method to continuously read the items as long as it returns true. Once it cannot read an item, you can ask it to stop. To perform this exercise, you can use either a while or a do...while loop. This would be done as follows: using System; using System.IO; using System.Xml; namespace VideoCollection1 {
C# 3.0 Practical Learning II
64
);
class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; FileStream fsVideos = new FileStream(strFilename, FileMode.Open, FileAccess.Read XmlTextReader rdrXml = new XmlTextReader(fsVideos ); do {
// Read an item and return true // Continue reading as long as ... } while (rdrXml.Read() == true); // ... as long as Read() returns true // Once Read() returns false, STOP!!! fsVideos.Close(); Console.WriteLine(); return 0; }
}
}
To identify what was read, the XmlTextReader provides methods appropriate for the different types of item that an XML file can contain. Starting in the next lesson, we will review the types of items of a file.
XML Wellformedness Tag Creation Earlier, we mentioned that XML worked through markups. A simple markup is made of a tag created between the left angle bracket "<" and the right angle bracket ">". Just creating a markup is not particularly significant. You must give it meaning. To do this, you can type a number, a date, or a string on the right side of the right angle bracket ">" symbol. The text on the right side of ">" is referred to as the item's text. It is also called a value. After specifying the value of the markup, you must close it: this is a rule not enforced in HTML but must be respected in XML to make it "well-formed". To close a tag, use the same formula of creating a tag with the left angle bracket "<", the tag, and the right angle bracket ">" except that, between < and the tag, you must type a forward slash. The formula to use is: C# 3.0 Practical Learning II
65
some value
The item on the left side of the "some value" string, in this case , is called the opening or start-tag. The item on the right side of the "some value" string, in this case , is called the closing or end-tag. Like is a markup, also is called a markup. With XML, you create your own tags with custom names. This means that a typical XML file is made of various items. Here is an example:
The Distinguished GentlemanJonathan Lynn112 Minutes
Practical Learning: Creating XML 1. Since we learned about the encoding declaration already, change the XmlDocument.Load() call as follows: using System; using System.Xml; namespace CollegeParkAutoParts1 { class Program { static int Main(string[] args) { XmlDocument docXML = new XmlDocument(); docXML.LoadXml(""); return 0; } } }
2. Save the file
Tag Names When creating your tags, there are various rules you must observe with regards to their names. Unlike HTML, XML is very restrictive with its rules. For example, unlike HTML but like C/C++/C#, XML is case-sensitive. This means that CASE, Case, and case are three different words. Therefore, from now on, you must pay close attention to what you write inside of the < and the > delimiters.
C# 3.0 Practical Learning II
66
Besides case sensitivity, there are some rules you must observe when naming the tags of your markups: •
The name of a tag must be in one word, no space in the name
•
The name must start with an alphabetic letter or an underscore - Examples are or <_salary>
•
The first letter or underscore that starts a name can be followed by:
•
o
Letters - Example:
o
Digits - Example:
o
Hyphens - Example:
o
Underscores - Example:
The name of a tag cannot start with xml, XML or any combination of X (uppercase or lowercase), followed by M (uppercase or lowercase), and followed by L (uppercase or lowercase)
In our lessons, here are the rules we will apply: •
A name will start in uppercase (most of the time) or lowercase
•
When a name is a combination of words, such as [hourly salary], we will start each part in uppercase. Examples will be HourlySalary or DateOfBirth
In future sections, we will learn that, with some markups, you can include non-readable characters between the angle brackets. In fact, you will need to pay close attention to the symbols you type in a markup. We will also see how some characters have special meaning.
The Root Every XML document must have one particular tag that, either is the only tag in the file, or acts as the parent of all the other tags of the same document. This tag is called the root. Here is an example of a file that has only one tag: A rectangle is a shape with 4 sides and 4 straight angles
This would produce:
C# 3.0 Practical Learning II
67
If there are more than one tag in the XML file, one of them must serve as the parent or root. Otherwise, you would receive an error. Based on this rule, the following XML code is not valid: A rectangle is a shape with 4 sides and 4 straight angles <square>A square is a rectangle whose 4 sides are equal
This would produce:
To correct this type of error, you can change one of the existing tags to act as the root. Here is an example:
C# 3.0 Practical Learning II
68
A rectangle is a shape with 4 sides and 4 straight angles <square>A square is a rectangle whose 4 sides are equal
This would produce:
Alternatively, you can create a tag that acts as the parent for the other tags. Here is an example: A rectangle is a shape with 4 sides and 4 straight angles <square>A square is a rectangle whose 4 sides are equal
This would produce:
As mentioned already, a good XML file should have a Document Type Declaration:
C# 3.0 Practical Learning II
69
A rectangle is a shape with 4 sides and 4 straight angles<square>A square is a rectangle whose 4 sides are equal
To provide access to the root of an XML file, the XmlDocument class is equipped with the DocumentElement property.
The Structure of an XML Tag Empty Tags We mentioned that, unlike HTML, every XML tag must be closed. We also saw that the value of a tag was specified on the right side of the right angle bracket of the start tag. In some cases, you will create a tag that doesn't have a value or, may be for some reason, you don't provide a value to it. Here is an example:
This type of tag is called an empty tag. Since there is no value in it, you may not need to provide an end tag but it still must be closed. Although this writing is allowed, an alternative is to close the start tag itself. To do this, between the tag name and the right angle bracket, type an empty space followed by a forward slash. Based on this, the above line can be written as follows:
Both produce the same result or accomplish the same role.
White Spaces In the above example, we typed various items on the same line. If you are creating a long XML document, although creating various items on the same line is acceptable, this technique can make it (very) difficult to read. One way you can solve this problem is to separate tags with empty spaces. Here is an example: The Distinguished Gentleman Jonathan Lynn 112 Minutes
Yet a better solution consists of typing each item on its own line. This would make the document easier to read. Here is an example: The Distinguished Gentleman Jonathan Lynn 112 Minutes
C# 3.0 Practical Learning II
70
All these are possible and acceptable because the XML parser doesn't consider the empty spaces or end of line. Therefore, to make your code easier to read, you can use empty spaces, carriagereturn-line-feed combinations, or tabs inserted in various sections. All these are referred to as white spaces.
Nesting Tags Most XML files contain more than one tag. We saw that a tag must have a starting point and a tag must be closed. One tag can be included in another tag: this is referred to as nesting. A tag that is created inside of another tag is said to be nested. A tag that contains another tag is said to be nesting. Consider the following example: <Smile>Please smile to the camera <English>Welcome to our XML Class Bienvenue à notre Classe XML
In this example, you may want the English tag to be nested in the Smile tag. To nest one tag inside of another, you must type the nested tag before the end-tag of the nesting tag. For example, if you want to nest the English tag in the Smile tag, you must type the whole English tag before the end tag. Here is an example: <Smile>Please smile to the camera<English>Welcome to our XML Class
To make this code easier to read, you can use white spaces as follows: <smile>Please smile to the camera <English>Welcome to our XML Class
When a tag is nested, it must also be closed before its nesting tag is closed. Based on this rule, the following code is not valid: <Smile>Please smile to the camera <English>Welcome to our XML Class
The rule broken here is that the English tag that is nested in the the Smile tag is not closed inside the Smile tag but outside.
Practical Learning: Creating XML 1. To apply the concept of nesting XML tags, change the Parts.xml file as follows:
C# 3.0 Practical Learning II
71
<Parts> <Part> 2005 <Make>Acura <Model>MDX 3.5 4WD <PartNumber>293749 <PartName>Air Filter 16.85 <Part> 2002 <Make>Audi <Model>A4 Quattro <PartNumber>283759 <PartName>Clutch Release Bearing 55.50
2. Access the Program.cs file and change the call to the XmlDocument.Load() method as follows: using System; using System.Xml; namespace CollegeParkAutoParts1 { class Program { static int Main(string[] args) { XmlDocument docXML = new XmlDocument(); docXML.LoadXml("" + "<Employees><Employee>" + "<EmplNumber>48-705" + "John" + "Cranston" + "16.48" + "<Employee>" + "<EmplNumber>22-688" + "Annie" + "Loskar" + "12.50" + "<Employee>" + "<EmplNumber>85-246" + "Bernie" + "Christo" + "22.52" +
C# 3.0 Practical Learning II
72
"<Employee>" ); docXML.Save("Employees.xml"); return 0; }
}
}
3. Execute the application 4. Close the DOS window 5. Open Windows Explorer and display the contents of the folder of the current project. Notice the presence of the parts.xml and the Employees.xml files 6. Double-click each file to preview it in the browser
C# 3.0 Practical Learning II
73
The Nodes of an XML Element An XML Node Introduction to XML Nodes Consider the following example of an XML file named Videos.xml:
An XML file appears as an upside-down tree: it has a root (in this case ), it can have branches (in this case <Title>Chalte C halteAziz Mirza145 MinsDVD N/R Press any key to continue . . .
The Child Nodes of a Node Introduction As mentioned already, one node can be nested inside of another. A nested node is called a child of the nesting node. This also implies that a node can have as many children as necessary, making them child nodes of the parent node. In our Videos.xml example, the Title and the Director nodes are children of the Video node. The Video node is the parent of both the Title and the Director nodes.
A Collection of Child Nodes To support the child nodes of a particular node, the XmlNode class is equipped with the ChildNodes property. To identify the collection of child nodes of a node, the .NET Framework provides the XmlNodeList class. Therefore, the ChildNodes property of an XmlNode object is of type XmlNodeList. This property is declared as follows: public virtual XmlNodeList ChildNodes{get};
When this property is used, it produces an XmlNodeList list, which is a collection of all nodes that share the same parent. Each item in the collection is of type XmlNode. To give you the number of nodes on an XmlNodeList collection, the class is equipped with a property named Count. Here is an example of using it:
using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml";
C# 3.0 Practical Learning II
94
XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elm = xmlDoc.DocumentElement; XmlNodeList lstVideos = elm.ChildNodes; Console.WriteLine("The root element contains {0} nodes",
lstVideos.Count); } else
located",
Console.WriteLine("The file {0} could not be strFilename); Console.WriteLine(); return 0;
}
}
}
This would produce: The root element contains 3 nodes Press any key to continue . . .
You can also use the Count property in a for loop to visit the members of the collection.
Accessing a Node in a Collection The children of a node, that is, the members of a ChildNodes property, or the members of an XmlNodeList collection, can be located each by an index. The first node has an index of 0, the second has an index of 1, an so on. To give you access to a node of the collection, the XmlNodeList class is equipped with an indexed property and a method named Item. Both produce the same result. For example, if a node has three children, to access the third, you can apply an index of 2 to its indexed property. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml";
C# 3.0 Practical Learning II
95
XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elm = xmlDoc.DocumentElement; XmlNodeList lstVideos = elm.ChildNodes; Console.WriteLine(lstVideos[2]);; } else
Console.WriteLine("The file {0} could not be
located",
} }
strFilename); Console.WriteLine(); return 0;
}
You can also use the Item() method to get the same result. Using a for loop, you can access each node and display the values of its children as follows: using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elm = xmlDoc.DocumentElement; XmlNodeList lstVideos = elm.ChildNodes; for (int i = 0; i < lstVideos.Count; i++) Console.WriteLine("{0}",lstVideos[i].InnerTe
xt ); } else located",
Console.WriteLine("The file {0} could not be strFilename); Console.WriteLine(); return 0;
C# 3.0 Practical Learning II
96
} }
}
This would produce: The Distinguished GentlemanJonathan Lynn112 MinutesDVDR Her AlibiBruce Beresford94 MinsDVDPG-13 Chalte ChalteAziz Mirza145 MinsDVDN/R Press any key to continue . . .
Instead of using the indexed property, the XmlNodeList class implements the IEnumerable interface. This allows you to use a foreach loop to visit each node of the collection. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elm = xmlDoc.DocumentElement; XmlNodeList lstVideos = elm.ChildNodes;
} else
foreach(XmlNode node in lstVideos) Console.WriteLine("{0}", node); Console.WriteLine("The file {0} could not be
located",
} }
strFilename); Console.WriteLine(); return 0;
}
This would produce: System.Xml.XmlElement System.Xml.XmlElement System.Xml.XmlElement Press any key to continue . . .
C# 3.0 Practical Learning II
97
To better manage and manipulate the nodes of a collection of nodes, you must be able to access the desired node. The XmlNode combined with the XmlNodeList classes provide various means of getting to a node and taking the appropriate actions.
The Parent of a Node Not all nodes have children, obviously. For example, the Title node of our Videos.xml file doesn't have children. To find out whether a node has children, check its HasChildNodes Boolean property that is declared as follows: public virtual bool HasChildNodes{get};
If a node is a child, to get its parent, you can access its ParentNode property.
The First Child Node The children of a nesting node are also recognized by their sequence. For our Videos.xml file, the first line is called the first child of the DOM. This would be:
After identifying or locating a node, the first node that immediately follows it is referred to as its first child. In our Videos.xml file, the first child of the first Video node is the <Title>The Distinguished Gentleman element. The first child of the second Video> node is <Title>Her Alibi. In the .NET Framework, the first child of a node can be retrieved by accessing the XmlNode.FirstChild property declared as follows: public virtual XmlNode FirstChild{get};
In the following example, every time the parser gets to a Video node, it displays the value of it first child: using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument();
C# 3.0 Practical Learning II
98
if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elm = xmlDoc.DocumentElement; XmlNodeList lstVideos = elm.ChildNodes; for (int i = 0; i < lstVideos.Count; i++) Console.WriteLine("{0}", lstVideos[i].FirstChild.InnerText ); } else located",
Console.WriteLine("The file {0} could not be strFilename); Console.WriteLine(); return 0;
}
}
}
This would produce: The Distinguished Gentleman Her Alibi Chalte Chalte Press any key to continue . . .
In this example, we started our parsing on the root node of the document. At times, you will need to consider only a particular node, such as the first child of a node. For example, you may want to use only the first child of the root. To get it, you can access the FirstChild property of the DocumentElement object of the DOM. Once you get that node, you can then do what you judge necessary. In the following example, only the values of the child nodes of the first child of the root are displayed: using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename);
C# 3.0 Practical Learning II
99
XmlNode node = xmlDoc.DocumentElement.FirstChild; XmlNodeList lstVideos = node.ChildNodes; for (int i = 0; i < lstVideos.Count; i++) Console.WriteLine("{0}", lstVideos[i].InnerText ); } else located",
Console.WriteLine("The file {0} could not be strFilename); Console.WriteLine(); return 0;
}
}
}
This would produce: The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R Press any key to continue . . .
Consider the following modification of the Videos.xml file: <Title>The Distinguished Gentleman Jonathan Lynn Eddie Murphy Lane Smith Sheryl Lee Ralph Joe Don Baker Victoria Rowell 112 Minutes DVD R <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 <Title>Chalte Chalte
C# 3.0 Practical Learning II
100
Aziz Mirza 145 Mins DVD N/R
Remember that when using a for or a foreach loop applied to an XmlNodeList collection, each node that you access is a complete XmlNode object and may have children. This means that you can further get the ChildNodes node of any node. Here is an example that primarily scans the nodes but looks for one whose name is CastMembers: using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Locate the root node and // get a reference to its first child XmlNode node = xmlDoc.DocumentElement.FirstChild; // Create a list of the child nodes of // the first node under the root XmlNodeList lstVideos = node.ChildNodes; // Visit each node for (int i = 0; i < lstVideos.Count; i++) { // Look for a node named CastMembers if (lstVideos[i].Name == "CastMembers") { // Once/if you find it, // 1. Access its first child // 2. Create a list of its child nodes XmlNodeList lstActors = lstVideos[i].ChildNodes; // Display the values of the nodes for (int j = 0; j < lstActors.Count; j+ +) }
Console.WriteLine("{0}", lstActors[j].InnerText);
C# 3.0 Practical Learning II
101
} } else Console.WriteLine("The file {0} could not be
located",
strFilename); Console.WriteLine(); return 0; }
}
}
This would produce: Eddie Murphy Lane Smith Sheryl Lee Ralph Joe Don Baker Victoria Rowell Press any key to continue . . .
As we have learned that a node or a group of nodes can be nested inside of another node. When you get to a node, you may know or find out that it has children. You may then want to consider only the first child. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Locate the root node and // get a reference to its first child XmlNode node = xmlDoc.DocumentElement.FirstChild; // Create a list of the child nodes of // the first node under the root XmlNodeList lstVideos = node.ChildNodes; // Visit each node for (int i = 0; i < lstVideos.Count; i++) { // Look for a node named CastMembers
C# 3.0 Practical Learning II
102
if (lstVideos[i].Name == "CastMembers") { // Once/if you find it, // 1. Access its first child // 2. Create a list of its child nodes XmlNodeList lstActors = lstVideos[i].FirstChild.ChildNodes; // Display the value of its first child
node
for (int j = 0; j < lstActors.Count; j+
+)
Console.WriteLine("{0}", lstActors[j].InnerText); }
}
} else located",
Console.WriteLine("The file {0} could not be strFilename); Console.WriteLine(); return 0;
}
}
}
This would produce: Eddie Murphy Press any key to continue . . .
The Last Child Node As opposed to the first child, the child node that immediately precedes the end-tag of the parent node is called the last child. To get the last child of a node, you can access its XmlNode.LastChild property that is declared as follows: public virtual XmlNode LastChild{get};
The Siblings of a Node The child nodes that are nested in a parent node and share the same level are referred to as siblings. Consider the above file: Director, CastMembers, and Length are child nodes of the Video node but the Actor node is not a child of the Video node. Consequently, Director, Actors, and Length are siblings. Obviously, to get a sibling, you must first have a node. To access the sibling of a node, you can use its XmlNode.NextSibling property, which is declared as follows: C# 3.0 Practical Learning II
103
public virtual XmlNode NextSibling{get};
C# 3.0 Practical Learning II
104
Operations on XML Elements Fundamental Operations Introduction So far, to create an XML element, we were directly typing in a file. When such a file has been created and saved, it is ready to be processed. Here is an example of a file named Videos.xml: <Title>The Distinguished Gentleman
In some applications, you will want the user to provide you with the necessary value(s) to create an element. Fortunately, XmlDocument, the XmlNode, and the XmlElement classes provide all the necessary properties and methods to perform the routine operations of an XML file, an element, or a node. The operations include locating a node, adding a new element, or deleting a node.
Before performing an operation, you will usually need to decide in what section of the file you want to action to bee applied. As it happens, you have the root node, a particular node inside the file, parent of a node, the sibling of a node, etc. To get to a node, you will usually first get a reference to its XmlElement. To do this, you can declare an XmlElement variable and initialize it with that reference.
Practical Learning: Introducing operations on XML Elements 1. Start Microsoft Visual C# and create a Console Application named CollegeParkAutoParts3 2. On the main menu, click Project -> Add New Item... 3. In the Templates list, click XML File
C# 3.0 Practical Learning II
105
4. Set the Name to makes and click Add 5. Change the file as follows: <Makes> <Make>Acura <Make>Audi <Make>BMW <Make>Chevrolet
6. On the main menu, click File -> Save makes.xml As... 7. Access the main folder of the current project and, inside of it, open a sub-folder of the same name (it should be opened already). In the sub-folder of the same name, open the bin subfolder followed by the Release sub-folder. Click Save 8. In the Solution Explorer, right-click CollegeParkAutoParts2 -> Add -> New Item... 9. In the Templates list, make sure XML File is selected. Set the Name to models and click Add 10. To save the file, on the main menu, click File -> Save models.xml As... 11. Access the main folder of the current project and, inside of it, open a sub-folder of the same name (it should be selected already). In the sub-folder of the same name, open the bin subfolder followed by the Release sub-folder. Click Save 12.
Change the file as follows:
<Models> <Model>NSX <Model>TL <Model>Spider <Model>A4 <Model>RS6 <Model>323I <Model>M5 <Model>Astro <Model>Cavalier <Model>Protégé
Adding an Empty Element
C# 3.0 Practical Learning II
106
To assist with programmatically creating a new element, the XmlDocument class provides the CreateElement() method that is overloaded with three versions. One of the versions uses the following syntax: public XmlElement CreateElement(string name);
Using this method, to create a new element, call it and pass it the name of the element. For example, imagine you want to add a new Title element to the above file. You would start with code as follows: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elmNew = xmlDoc.CreateElement("Title"); } Console.WriteLine(); return 0; }
}
}
In order to add the new element to the file, you must specify its position in the tree: whether it would be the first or the last node, whether you want to position it before or after a node of your choice. For example, if you want to add a new Title element to the above file, it would be considered a child of the root, that is, a child of the XmlDocument.DocumentElement property. In the previous lesson, we learned how to get a reference to the root node. To support the positions of existing nodes, the XmlNode class, which is the ancestor of all XML nodes of the .NET Framework, provides various appropriate methods. One of these methods is AppendChild(), which is used to add an element as the last child of its parent. The syntax of the XmlNode.AppendChild() method is: public virtual XmlNode AppendChild(XmlNode newChild);
C# 3.0 Practical Learning II
107
When calling this method, pass the XmlNode object you had previous created. After adding the node, if you want the file to keep it, you should save it. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elmRoot = xmlDoc.DocumentElement; XmlElement elmNew = xmlDoc.CreateElement("Title"); elmRoot.AppendChild(elmNew); xmlDoc.Save(strFilename); } Console.WriteLine(); return 0; }
}
}
This would produce: <Title>The Distinguished Gentleman <Title />
Notice that the newly added element is empty.
Adding an Element With Value If you want the element to have a value, the XmlDocument class provides the CreateTextNode() method. This method returns an XmlText value. The syntax of this method is: public virtual XmlText CreateTextNode(string text);
This method takes as argument the string that would constitute the value of the element. Before calling it, you should have used the
C# 3.0 Practical Learning II
108
XmlNode.AppendChild() method to create a node. Calling this method on the LastChild node of the one that called the AppendChild() would specify the value of the new node. Here is an
example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elmRoot = xmlDoc.DocumentElement; XmlElement elmNew = xmlDoc.CreateElement("Title"); XmlText txtVideo = xmlDoc.CreateTextNode("Basic Instinct"); elmRoot.AppendChild(elmNew); elmRoot.LastChild.AppendChild(txtVideo); xmlDoc.Save(strFilename); } Console.WriteLine(); return 0; }
}
}
This would produce: <Title>The Distinguished Gentleman <Title /> <Title>Basic Instinct
The combination of calls to XmlDocument.CreateElement() and XmlDocument.CreateTextNode() allow you to create a new element that has a value. Consider the following file:
C# 3.0 Practical Learning II
109
<Title>The Distinguished Gentleman <Title>Basic Instinct
Notice that the root, Videos, has a repetitive child named Video. This Video child has its own child named Title. Imagine that you want to add a new Video node that has a child. To do this, first create an empty Video node as a child of the root. We learned earlier how to do that: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elmRoot = xmlDoc.DocumentElement; XmlElement elmNew = xmlDoc.CreateElement("Video"); elmRoot.AppendChild(elmNew); }
} }
Console.WriteLine(); return 0;
}
After creating the new child of the root, initialize the grand child with the desired name (the name doesn't have to be one of the existing names) and a value (which is optional if you don't want the new node to have a value). Once the new node is ready, append it as the last child of the root. If this new node has a value, append its XmlText object as the LastChild of the LastChild of the root. Here is an example of how you would do this: using System; using System.IO; using System.Xml;
C# 3.0 Practical Learning II
110
namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elmRoot = xmlDoc.DocumentElement; XmlElement elmNew = xmlDoc.CreateElement("Video"); elmRoot.AppendChild(elmNew); elmRoot = xmlDoc.DocumentElement; elmNew = xmlDoc.CreateElement("Title"); XmlText txtVideo = xmlDoc.CreateTextNode("Her
Alibi");
elmRoot.LastChild.AppendChild(elmNew); elmRoot.LastChild.LastChild.AppendChild(txtVideo
);
xmlDoc.Save(strFilename); } Console.WriteLine(); return 0; }
}
}
With this code you would go from this: <Title>The Distinguished Gentleman <Title>Basic Instinct
To this: <Title>The Distinguished Gentleman
C# 3.0 Practical Learning II
111
<Title>Basic Instinct <Title>Her Alibi
Now consider the following file: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13
The root, Videos, has a child named Video. The Video node has many child nodes. By now, we know how to add a child to the root. We also saw how to add a grand child with value to the root. To had many (grand) children to a node, first build the node, add it to the root, then continuously add the necessary nodes, one at a time, including its name and its optional value. This would be done as follows: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elmRoot = xmlDoc.DocumentElement;
C# 3.0 Practical Learning II
112
XmlElement elmNew = xmlDoc.CreateElement("Video"); elmRoot.AppendChild(elmNew); elmRoot = xmlDoc.DocumentElement; elmNew = xmlDoc.CreateElement("Title"); XmlText txtVideo = xmlDoc.CreateTextNode("The Day After Tomorrow"); elmRoot.LastChild.AppendChild(elmNew); elmRoot.LastChild.LastChild.AppendChild(txtVideo ); elmNew = xmlDoc.CreateElement("Director"); txtVideo = xmlDoc.CreateTextNode("Roland Emmerich");
elmRoot.LastChild.AppendChild(elmNew); elmRoot.LastChild.LastChild.AppendChild(txtVideo
);
elmNew = xmlDoc.CreateElement("Length"); txtVideo = xmlDoc.CreateTextNode("124 Minutes"); elmRoot.LastChild.AppendChild(elmNew); elmRoot.LastChild.LastChild.AppendChild(txtVideo
);
elmNew = xmlDoc.CreateElement("Format"); txtVideo = xmlDoc.CreateTextNode("DVD"); elmRoot.LastChild.AppendChild(elmNew); elmRoot.LastChild.LastChild.AppendChild(txtVideo
);
elmNew = xmlDoc.CreateElement("Rating"); txtVideo = xmlDoc.CreateTextNode("PG-13"); elmRoot.LastChild.AppendChild(elmNew); elmRoot.LastChild.LastChild.AppendChild(txtVideo
);
xmlDoc.Save(strFilename); } Console.WriteLine(); return 0; }
}
}
This would produce: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD
C# 3.0 Practical Learning II
113
R <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13
Using the same approach, you can add children to children of children, and so on.
Practical Learning: Programmatically Adding an Element 1. To give the user the ability to create a new car make, change the Program.cs file as follows: using System; using System.Xml; namespace CollegeParkAutoParts3 { public static class Program { public static void CreateNewMake() { string strNewMake = ""; Console.Write("Enter Car Make: "); strNewMake = Console.ReadLine(); // Open the Makes.xml file XmlDocument docXMLFile = new XmlDocument(); docXMLFile.Load("Makes.xml");
elements
// Get the root node so we can explore its children XmlElement nodRoot = docXMLFile.DocumentElement; // Store all the values of the elements in a string string allMyChildren = nodRoot.InnerText; // Locate the new make among the values of the int indexLookForNewMake = allMyChildren.IndexOf(strNewMake);
C# 3.0 Practical Learning II
114
// If the car make exists already, don't add it if (indexLookForNewMake >= 0) return; else { // If the car is not in the list // already, add it as a Make element XmlElement elmXML = docXMLFile.CreateElement("Make"); // Create its value using the // string provided by the user XmlText txtXML = docXMLFile.CreateTextNode(strNewMake); // Add the new element at the end of the file docXMLFile.DocumentElement.AppendChild(elmXML); // Specify its text docXMLFile.DocumentElement.LastChild.AppendChild (txtXML); // Save the file docXMLFile.Save("Makes.xml"); }
}
}
static int Main(string[] args) { return 0; }
}
2. To give the user the ability to add a new car model, create the following function in the file: using System; using System.Xml; namespace CollegeParkAutoParts2 { public static class Program { public static void CreateNewMake() { . . . No Change } public static void CreateNewModel() { string strNewModel = ""; Console.Write("Enter Car Model: "); strNewModel = Console.ReadLine(); XmlDocument docXMLFile = new XmlDocument(); docXMLFile.Load("models.xml");
C# 3.0 Practical Learning II
115
XmlElement nodRoot = docXMLFile.DocumentElement; string allMyChildren = nodRoot.InnerText; int indexNewModel = allMyChildren.IndexOf(strNewModel); if (indexNewModel >= 0) return; else { XmlElement elmXML = docXMLFile.CreateElement("Model"); XmlText txtXML = docXMLFile.CreateTextNode(strNewModel); docXMLFile.DocumentElement.AppendChild(elmXML); docXMLFile.DocumentElement.LastChild.AppendChild (txtXML); }
docXMLFile.Save("models.xml");
} static int Main(string[] args) { return 0; } }
}
3. To guide the user with a menu, change the file as follows: using System; using System.Xml; namespace CollegeParkAutoParts2 { public static class Program { public static void CreateNewMake() { . . . No Change } public static void CreateNewModel() { . . . No Change } static int Main(string[] args) { char mnuChoice = 'q'; Console.WriteLine("=o=o=o=o=o=o=o=o=o=o=o=o=o=o=o=") ;
C# 3.0 Practical Learning II
116
Console.WriteLine("=-= College Park Auto-Parts ==");
Console.WriteLine("=o=o=o=o=o=o=o=o=o=o=o=o=o=o=o=")
; do { try { Console.WriteLine("=-= Main Menu =-="); Console.WriteLine("1 - Add New Car Make"); Console.WriteLine("2 - Add New Car Model"); Console.WriteLine("0 - Exit"); Console.Write("Your Choice: "); mnuChoice = char.Parse(Console.ReadLine()); } catch (FormatException) { Console.WriteLine("Invalid Choice"); Console.WriteLine("Please try again"); } switch (mnuChoice) { case '1': CreateNewMake(); break; case '2': CreateNewModel(); break; default: break; } Console.WriteLine(); } while((mnuChoice == '1') || (mnuChoice == '2'));
} }
Console.WriteLine("\nThank you!"); return 0;
}
4. Execute the application and create the following elements:
Makes
Dodge Ford
C# 3.0 Practical Learning II
117
Honda Toyota Models
A4 Quattro Corolla Dakota Focus Escort Camry Crown Victoria Expedition Integra Neon 5. Close the DOS window
Adding a Filled Child Element The above Videos.xml file had only one level under the root and no child element of the root had children. Suppose you have the following version of the file: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R
C# 3.0 Practical Learning II
118
<Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13
Imagine that you want to add a Video element. You have a choice of adding one, more, or all child elements of the Video node. To perform this operation, one solution you can use is to "build" all child elements of the Video element, then add the node as a whole. To support this technique, we saw earlier that the XmlNode.InnerXml property comprises a node, its markup, its children and their markup. This means that you can create the child nodes with their markup(s) as a string and assign that string to an XmlNode.InnerXml string. To do this, you would need the set version of the InnerXml property. It is declared as follows: public virtual string InnerXml{get; set;}
Here is an example that adds a complete new Video node to the above XML file: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); XmlElement elmXML = xmlDoc.CreateElement("Video"); string strNewVideo = "<Title>Other People's Money" + "Alan Brunstein" + "114 Minutes" + "VHS" + "PG13"; elmXML.InnerXml = strNewVideo;
C# 3.0 Practical Learning II
119
xmlDoc.DocumentElement.AppendChild(elmXML); xmlDoc.Save("Videos.xml"); } Console.WriteLine(); return 0; }
}
}
Inserting an Element Locating an Element So far, we have been adding nodes quite randomly, that is, without much precision. In some cases, you may want to perform an operation on an existing and particular node. For example, you may want to change the value of a node, you may want to add a new child node to an existing node, etc. Before taking any of these actions, you must be able to locate or identify the desired element. To assist you with finding a node, the XmlDocument class is equipped with the GetElementByTagName() method which is overloaded with two versions. One of the syntaxes used is: public virtual XmlNodeList GetElementsByTagName(string name);
This method takes as argument a string. The string must be the Name of a node. If at least one node that holds that name exists in the file, this method returns a collection of the nodes with that name. If there is no node with that name, the collection is returned empty and there is no exception. Here is an example of calling the method: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) {
C# 3.0 Practical Learning II
120
xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title");
}
} }
// Now you can check each node of the list foreach(XmlNode node in lstTitles) { ; }
Console.WriteLine(); return 0;
}
Once you have a list of the nodes of a particular criterion, you can then act as you see fit. For example, For example, you can look for a particular node that holds a text of your choice. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; //XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("Video"); // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title"); // Now you can check each node of the list foreach(XmlNode node in lstTitles) { if (node.InnerText == "Her Alibi")
C# 3.0 Practical Learning II
121
{ } }
} }
;
}
Console.WriteLine(); return 0;
}
Inserting an Element as a Last Child Once again, consider our Videos.xml file: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13
Imagine you want to add a list of actors of the Her Alibi video. The first action to take is to locate the video, which you can do by calling the XmlDocument.GetElementsByTagName() method applied to a collection of nodes whose names are Video. From this list of nodes, you can look for the node whose value is "Her Alibi". Once you have found this element, get a reference to its parent. Then add the new node as the LastChild object of its parent. This can be done as follows: using System; using System.IO; using System.Xml;
C# 3.0 Practical Learning II
122
namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title");
element's value
// visit each node named Title foreach(XmlNode node in lstTitles) { // When you get to a node, look for the // If you find an element whose value is Her
Alibi
if (node.InnerText == "Her Alibi") { // Create an element named Actors XmlElement elmNew = xmlDoc.CreateElement("Actors"); XmlNode elmParent = node.ParentNode; // Add a new element named Actors to it elmParent.AppendChild(elmNew); xmlDoc.Save(strFilename); } } }
} }
Console.WriteLine(); return 0;
}
This would produce: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R
C# 3.0 Practical Learning II
123
<Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13
This code creates an empty element. If you want to create an element that includes a value, create its text and add that text as the LastChild of its parent. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title");
element's value Alibi Gentleman")
// visit each node named Title foreach(XmlNode node in lstTitles) { // When you get to a node, look for the // If you find an element whose value is Her if (node.InnerText == "The Distinguished {
C# 3.0 Practical Learning II
124
// Create an element named Category XmlElement elmNew = xmlDoc.CreateElement("Category"); // Create the text of the new element XmlText txtCatetory = xmlDoc.CreateTextNode("Comedy"); // Get a reference to the parent of the node we have found
XmlNode elmParent = node.ParentNode; // Add the new element to the node we
found
elmParent.AppendChild(elmNew); // Specify the text of the new node elmParent.LastChild.AppendChild(txtCatet
ory);
// Save the file xmlDoc.Save(strFilename); }
}
} Console.WriteLine(); return 0; }
}
}
This would produce: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R Comedy <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13
C# 3.0 Practical Learning II
125
Using the same approach combined with what we learned about adding an item, you can add a new element that itself has child nodes. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose name is Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title");
element's value
// visit each node named Title foreach(XmlNode node in lstTitles) { // When you get to a node, look for the
Day After Tomorrow Tomorrow")
// If you find an element whose value is The if (node.InnerText == "The Day After {
// Create an element named Actors XmlElement elmNew = xmlDoc.CreateElement("Actors"); // Get a reference to the parent of the node we have found XmlNode elmVideo = node.ParentNode; // Add the new element to the node we found elmVideo.AppendChild(elmNew); // Create an element as a child of the new element
// Specify its name as Actor elmNew = xmlDoc.CreateElement("Actor"); // Create the text of the new element XmlText txtActor = xmlDoc.CreateTextNode("Dennis Quaid");
C# 3.0 Practical Learning II
126
// Add the new Actor element to the Actors node
elmVideo.LastChild.AppendChild(elmNew); // Specify the text of the new node elmVideo.LastChild.LastChild.AppendChild
(txtActor); // In the same way, add the other Actor
nodes
elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("Jake Gyllenhaal");
elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild
(txtActor);
elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("Emmy
Rossum");
elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild (txtActor); elmNew = xmlDoc.CreateElement("Actor"); txtActor = xmlDoc.CreateTextNode("Dash Mihok");
elmVideo.LastChild.AppendChild(elmNew); elmVideo.LastChild.LastChild.AppendChild
(txtActor);
} }
} }
// Save the file xmlDoc.Save(strFilename);
}
Console.WriteLine(); return 0;
}
This would produce: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R Comedy <Title>Her Alibi
C# 3.0 Practical Learning II
127
Bruce Beresford 94 Mins DVD PG-13 <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13 Dennis Quaid Jake Gyllenhaal Emmy Rossum Dash Mihok
You can also insert one or more elements as children of an existing node after locating that node. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of nodes whose names are Title XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("Title");
element's value Alibi
// visit each node named Title foreach(XmlNode node in lstTitles) { // When you get to a node, look for the // If you find an element whose value is Her if (node.InnerText == "Her Alibi")
C# 3.0 Practical Learning II
128
{ that is Alibi
// Get a reference to the video node // the parent of the video titled Her XmlNode elmVideo = node.ParentNode;
the Her alibi video elmVideo.ChildNodes;
// Create a list of the child nodes of XmlNodeList lstActors = // Visit each item of the collection // looking for an element named Actors foreach (XmlNode nodActor in lstActors) { // If you find an element named
Actors
if (nodActor.Name == "Actors") { // Create a new element named
Actor xmlDoc.CreateElement("Actor");
// Specify its name as Actor XmlElement elmNew = // Create the text of the new
element
XmlText txtActor = xmlDoc.CreateTextNode("Tom Selleck"); // Add the new Actor element to the Actors node elmVideo.LastChild.AppendChild(e lmNew); // Specify the text of the new node elmVideo.LastChild.LastChild.App endChild(txtActor);
xmlDoc.CreateElement("Actor");
// Add other Actor nodes elmNew =
txtActor = xmlDoc.CreateTextNode("Paulina Porizkova"); elmVideo.LastChild.AppendChild(e lmNew); elmVideo.LastChild.LastChild.App endChild(txtActor); elmNew = xmlDoc.CreateElement("Actor");
txtActor = xmlDoc.CreateTextNode("William Daniels"); elmVideo.LastChild.AppendChild(e lmNew); elmVideo.LastChild.LastChild.App endChild(txtActor);
C# 3.0 Practical Learning II
129
// Save the file xmlDoc.Save(strFilename); // Stop, in this example, we don't expect another Actors node } }
break; }
}
} Console.WriteLine(); return 0; }
}
}
This would produce: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R Comedy <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 Tom Selleck Paulina Porizkova William Daniels <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13 Dennis Quaid Jake Gyllenhaal Emmy Rossum Dash Mihok
C# 3.0 Practical Learning II
130
Practical Learning: Adding Elements 1. In the Solution Explorer, right-click CollegeParkAutoParts3 -> Add -> New Item... 2. In the Templates list, make sure XML File is selected. Set the Name to parts and click Add 3. Change the file as follows: <Parts> <Part> <PartNumber>293749 <Make>Acura <Model>MDX 3.5 4WD 2005 <PartName>Air Filter 16.85 <Part> <PartNumber>283759 <Make>Audi <Model>A4 Quattro 2002 <PartName>Clutch Release Bearing 55.50 <Part> <PartNumber>491759 <Make>Dodge <Model>Neon 1998 <PartName>Crankshaft Position Sensor 22.85 <Part> <PartNumber>844509 <Make>Chevrolet <Model>Camaro 2000 <PartName>Control Module Connector 25.65
4. To save the file, on the main menu, click File -> Save parts.xml As...
C# 3.0 Practical Learning II
131
5. Access the main folder of the current project and, inside of it, open a sub-folder of the same name (you should be in that folder already). In the sub-folder of the same name, open the bin sub-folder followed by the Release sub-folder. Click Save 6. To allow the user to create new parts, change the Program.cs file as follows: using System; using System.Xml; namespace CollegeParkAutoParts3 { public static class Program { public static void CreateNewMake() { . . . No Change } public static void CreateNewModel() { . . . No Change } public static void AddNewPart() { int carYear; string strMake, strModel, strPartNumber, strPartName; double unitPrice; // - Generate a random number between 100000 and 999999 - // // We will generate a random number for the item // To start, we will use the miliseconds as a seed int ms = DateTime.Now.Millisecond; Random rndNumber = new Random(ms); int next = rndNumber.Next(100000, 999999); // Display the new number in the Part # text box strPartNumber = next.ToString(); - ////
//// - Let the user specify the car model year int curYear = DateTime.Now.Year + 1;
+ part");
Console.WriteLine("Enter the following information " "as is related to the new car Console.WriteLine("For the car model that the " + "new part is made for, enter the
year");
C# 3.0 Practical Learning II
132
Console.Write("between 1960 and " + curYear + ": "); carYear = int.Parse(Console.ReadLine()); one - //
// - Display the list of Makes to the user to select // We will need a reference to the XML document XmlDocument docXML = new XmlDocument(); // Open the Makes.xml file docXML.Load("Makes.xml");
=");
// Get a reference to the root node XmlElement nodRoot = docXML.DocumentElement; // Locate all nodes whose name is Make XmlNodeList nodItems = nodRoot.GetElementsByTagName("Make"); // Retrieve the value of each Make node and display // that value to the user Console.WriteLine("Here is a list of the car " + "makes in our system"); for (int i = 0; i < nodItems.Count; i++) Console.WriteLine(nodItems[i].InnerXml); Console.Write("From this list, enter the car " + "make of the new part: "); strMake = Console.ReadLine(); Console.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=// - Display the list of car Models to the // user to select one - // // Open the Models.xml file docXML.Load("Models.xml"); // Get a reference to the root node nodRoot = docXML.DocumentElement; // Locate all nodes whose name is Model nodItems = nodRoot.GetElementsByTagName("Model"); // Retrieve the value of each Model node and display // that value to the user Console.WriteLine("Here is a list of the " + "car models in our system"); for (int i = 0; i < nodItems.Count; i++) Console.WriteLine(nodItems[i].InnerXml); Console.Write("From this list, enter the car " + "model of the part: "); strModel = Console.ReadLine(); Console.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
="); //// - Request the part name - //// Console.Write("Enter Part Name: "); strPartName = Console.ReadLine(); //// - Request the unit price - ////
C# 3.0 Practical Learning II
133
Console.Write("Enter Unit Price: "); unitPrice = double.Parse(Console.ReadLine()); Console.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
=");
Console.WriteLine("New Car Part Summary"); Console.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-==");
Console.WriteLine("Part #: " + strPartNumber); Console.WriteLine("Model Year: " + carYear); Console.WriteLine("Car Make: " + strMake); Console.WriteLine("Car Model: " + strModel); Console.WriteLine("Part Name: " + strPartName); Console.WriteLine("Unit Price: " + unitPrice); Console.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
="); // XmlDocument docXML = new XmlDocument(); docXML.Load("Parts.xml"); XmlElement elmXML = docXML.CreateElement("Part"); string strNewPart = "<PartNumber>" + strPartNumber + "" + "" + carYear.ToString()
+
"" + "<Make>" + strMake + "" + "<Model>" + strModel +
"" +
"<PartName>" + strPartName + "" + "" + unitPrice.ToString() +
"";
elmXML.InnerXml = strNewPart; docXML.DocumentElement.AppendChild(elmXML); }
docXML.Save("Parts.xml");
static int Main(string[] args) { char mnuChoice = 'q'; Console.WriteLine("=o=o=o=o=o=o=o=o=o=o=o=o=o=o=o=") ; =");
Console.WriteLine("=-= College Park Auto-Parts =Console.WriteLine("=o=o=o=o=o=o=o=o=o=o=o=o=o=o=o=")
; do { try { Console.WriteLine("=-= Main Menu =-=");
C# 3.0 Practical Learning II
134
Console.WriteLine("1 - Add New Car Make"); Console.WriteLine("2 - Add New Car Model"); Console.WriteLine("3 - Add New Part"); Console.WriteLine("0 - Exit"); Console.Write("Your Choice: "); mnuChoice = char.Parse(Console.ReadLine());
} catch (FormatException) { Console.WriteLine("Invalid Choice"); Console.WriteLine("Please try again"); } switch (mnuChoice) { case '1': CreateNewMake(); break; case '2': CreateNewModel(); break; case '3': AddNewPart(); break; default: break; } Console.WriteLine(); } while((mnuChoice == '1') || (mnuChoice == '2') || (mnuChoice == '3') ); Console.WriteLine("\nThank you!"); return 0; }
}
}
7. Execute the application and create the following parts:
Part Name
Unit Price
1986 Acura Integra
Alternator
110.75
1996 Dodge Neon
Brake Pads
34.95
1996 Honda Civic
Passenger Mirror
24.65
Year Make
Model
C# 3.0 Practical Learning II
135
2002 Audi
A4 Quattro Exhaust Gasket
1.55
1998 Honda Civic
Brake Pads
34.85
2004 Dodge Neon
Radiator Fan Assembly
125.95
2002 Audi
A4 Quattro Axle Differential Bearing - Left
10.25
2000 Ford
Escort
Crankshaft Position Sensor
18.65
1998 Toyota Corolla
Radiator
95.95
2004 Dodge Neon
Oil Pump
112.85
2004 Honda Civic
Oxygen Sensor
90.55
2000 Ford
Right Caliper Assembly Front
32.85
Exhaust Valve
5.85
Escort
2004 Dodge Neon 2002 Audi
A4 Quattro Alternator
305.50
1986 Acura Integra
Fuel Cap (Regular)
4.15
2004 Dodge Neon
Clutch Release Bearing
25.75
2002 Dodge Dakota
Starter Motor
145.95
2002 Acura NSX
Oil Filter
7.05
1998 BMW
Rack and Pinion Bellow Kit
19.25
Voltage Regulator
215.75
325I
2001 Acura Integra 2002 Audi
A4 Quattro Muffler Hanger
C# 3.0 Practical Learning II
3.35
136
2002 Acura NSX
Oil Drain Plug
1.35
2002 Dodge Dakota
Circuit Breaker
3.25
2004 Dodge Neon
Brake Pad
20.55
2004 Honda Civic
Fusible Link
3.35
2002 Dodge Dakota
Circuit Breaker
3.45
2004 Honda Civic
Differential Bearing
36.75
1998 Toyota Corolla
Thermostat Standard Temperature
9.35
2002 Audi
A4 Quattro Cooling Fan Sensor
8.65
2002 Acura NSX
Oil Pump Seal
12.55
2004 Dodge Neon
Master Cylinder w/o ABS w/2 Wheel
102.95
2002 Acura NSX
Valve Stem Oil Seal
1.75
2002 Dodge Dakota
Fuse
0.40
1998 Toyota Corolla
Regular Thermostat
11.15
8. Close the DOS window
Insertion an Element Referencing a Sibling Instead of simply adding a new node at the end of child nodes, you can specify any other position you want. For example, you may want the new node to precede an existing child node. To support this operation, the XmlNode class provides the InsertBefore() method. Its syntax is:
C# 3.0 Practical Learning II
137
public virtual XmlNode InsertBefore(XmlNode newChild, XmlNode refChild);
The first argument of this method is the new node that will be added. The second argument is the sibling that will succeed the new node. Consider the following version of our Videos.xml file: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R Comedy <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 <Title>Fatal Attraction Adrian Lyne 119 Minutes DVD R <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13
Imagine you want to create a new Category element below the Director element whose name is Adrian Lyne. You can first get a list of videos. Inside of each video, check the nodes and find out whether the video has a Director node whose text is Adrian Lyne. Once you find that node, you can add the new element after it. Here is an example: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program {
C# 3.0 Practical Learning II
138
static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of the videos XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("Video"); // visit each video foreach (XmlNode node in lstVideos) { // Within a video, create a list of its
children
XmlNodeList lstChildren = node.ChildNodes; // Visit each child node foreach (XmlNode dir in lstChildren) { // If the child node is (a director and its name is) Adrian Lyne if (dir.InnerText == "Adrian Lyne") { // Create an element named Category XmlElement elmNew = xmlDoc.CreateElement("Category"); // Specify the text of the new element elmNew.InnerText = "Drama";
Adrian Lyne node Director
// Insert the new node below the node.InsertAfter(elmNew, dir); // Save the file xmlDoc.Save(strFilename);
} }
// Stop break;
}
} Console.WriteLine(); return 0; }
C# 3.0 Practical Learning II
139
} }
This would produce: <Title>The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R Comedy <Title>Her Alibi Bruce Beresford 94 Mins DVD PG-13 <Title>Fatal Attraction Adrian Lyne Drama 119 Minutes DVD R <Title>The Day After Tomorrow Roland Emmerich 124 Minutes DVD PG-13
In the same way, you can insert a new node after a child of a child (of a child of a child of a child) of any node. If you want to new node to be positioned after an existing child node, you can call the XmlNode.InsertAfter() method. Its syntax is: public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild);
Node Removal If you have a node you don't want or don't need anymore in the file, you can delete it. To delete a node, the XmlNode class provides the RemoveChild() method. Its syntax is: C# 3.0 Practical Learning II
140
public virtual XmlNode RemoveChild(XmlNode oldChild);
This method takes as argument the node to delete. If the node exists, it would be deleted and the method would return it. If the node doesn't exist, nothing would happen. To effectively use this method, you should first locate the particular node you want to delete. You can look for it using any of the logics we have applied so far. Once you find the node, you can then delete it. Imagine you want to delete a node whose name is Director and whose value is Bruce Beresford. Here is an example of calling this method to perform the operation: using System; using System.IO; using System.Xml; namespace VideoCollection1 { class Program { static int Main(string[] args) { string strFilename = "Videos.xml"; XmlDocument xmlDoc = new XmlDocument(); if (File.Exists(strFilename)) { xmlDoc.Load(strFilename); // Get a reference to the root node XmlElement elmRoot = xmlDoc.DocumentElement; // Create a list of the videos XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("Video"); // visit each video foreach (XmlNode node in lstVideos) { // Within a video, create a list of its children
XmlNodeList lstChildren = node.ChildNodes; // Visit each child node foreach (XmlNode dir in lstChildren) { // If the child node is Bruce Beresford if (dir.InnerText == "Bruce Beresford") { node.RemoveChild(dir); // Save the file xmlDoc.Save(strFilename); // Stop
C# 3.0 Practical Learning II
141
break; } }
}
}
}
Console.WriteLine(); return 0;
}
}
To
delete
all
child
nodes
of
a
node,
you
can
call
the
XmlNode.RemoveAll() method. Its syntax is: public virtual void RemoveAll();
When called, this method will remove all child nodes, if any, of their parent node.
C# 3.0 Practical Learning II
142
The Attributes of an XML Element Fundamentals of Attributes Introduction When studying XML elements we saw how they constituted the main objects of an XML document. We also saw that an element could be nested inside of another element. Instead of nesting an element, you can transform the nested element into being part of the nesting element and thereby giving away its element qualities. This is the basis of an attribute. An attribute is a value that is created as part of an element, making that value different from the value of a regular element. There are similarities and differences between an element and an attribute. The element and the attribute have these in common: •
Both (must) have a name
•
Each may or may not have a value
The differences between an element and an attribute are: •
An attribute is considered a characteristic of an element. This means that an attribute belongs to an element
•
An element can have one or more attributes. An attribute cannot have an element
•
An attribute must be created in the start-tag of an element
•
An element cannot be defined as part of an attribute. That is, an attribute is subject to an element and an attribute doesn't own the attribute
Practical Learning: Introducing Attributes
C# 3.0 Practical Learning II
143
1. Create a new Console Application named CountriesStatistics1
2. To save the file, on the Standard toolbar, click the Save All button 3. Accept all defaults and click Save 4. In the Solution Explorer, right-click CountriesStatistics1 -> Add -> New Item... 5. In the Templates list, click XML File 6. Set the Name to continents and click Add 7. Change the file as follows: <World>
8. To save the file, on the main menu, click File -> Save continents.xml As... 9. Access the main folder of the current project and, inside of it, open a sub-folder of the same name (you should be in that folder already). In the sub-folder of the same name, open the bin sub-folder followed by the Release sub-folder. Click Save
Creating an Attribute An attribute must be created inside the start-tag of an element. To manually create an attribute, type the left angle bracket of the element, followed by the name of the element, an empty space, and the name of the attribute. The name follows the same rules we defined for names in XML. An attribute should have a value that can be used to distinguish it. To specify the name of an attribute, assign a value as a string to its name. Imagine you have an ISBN element as a child of a Video element as follows: 0-7888-1623-3
In this case, since ISBN is simply a child of the Video element, you can change the ISBN element to become an attribute of the Video element as follows:
Now, ISBN is an attribute of the Video element. C# 3.0 Practical Learning II
144
Operations
on an XML Attribute
Introduction In the .NET Framework, an attribute is represented by the XmlAttribute class. Like all nodes, this class is based on the XmlNode class. The name of an attribute is represented by its (read-only) Name property. The value of an attribute is represented by its Value property . Besides Value, you can also use XmlAttribute.InnerText or XmlAttribute.InnerXml to access the text of an attribute.
Manually Creating an Attribute An element can have 0, one, or more attributes. The attributes of an element are stored in the Attributes property of an XmlElement object. The XmlElement.Attributes property is based on a class called XmlAttributeCollection. The XmlAttributeCollection class is based on the XmlNamedNodeMap class. Before performing an attribute-related operation on an element, to find out whether the element has any attribute, you can check the value of the Boolean HasAttributes property of its XmlElement element. If this property produces a true value, then the element has at least one attribute; otherwise, the element doesn't have any. While a certain element may have an attribute, a sibling element with the same name may not have an attribute or may have a completely different type of attribute. Here is an XML file with attributes in some elements: <Title Screenplay="Marty Kaplan">The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R <Title WrittenBy="Charlie Peter">Her Alibi Bruce Beresford 94 Mins DVD PG-13
C# 3.0 Practical Learning II
145
Remember that you can include white spaces to make your code easy to read. This means that you can type an attribute on the next line of its element's name. In the Lesson 36, we saw that every element must be closed. We saw that we could close an element with an end-tag as follows: 0-7888-1623-3
We also saw that we could close an element locally as follows: . If you create an attribute in an empty element, you can also close it by typing the indicative forward slash before the right angle bracket and after an empty space. Here is an example:
Practical Learning: Creating Simple Attributes 1. Change the file continents.xml file as follows: <World>
2. Save the file
Programmatically Creating an Attribute As mentioned already, an attribute primarily belongs to an element. This means that, when creating an attribute, you must specify what element it would belong to. To support the attributes of an element, the XmlElement class is equipped with the SetAttribute() method which is overloaded in two versions. The first version of this method uses the following syntax: public virtual void SetAttribute(string name, string value);
The first argument is the name of the new attribute and the second argument will be its text. Before adding an attribute, you should first identify its parent element. Here is an example that adds an attribute to the root element: using System; using System.IO; using System.Xml;
C# 3.0 Practical Learning II
146
namespace VideoCollection { public static class Exercise { private static void CreateAttribute() { string strFilename = "Videos.xml"; XmlDocument docXML = new XmlDocument(); if (File.Exists(strFilename)) { // Open the XML file docXML.Load(strFilename); // Create an attribute and add it to the root
element
}
docXML.DocumentElement.SetAttribute("FileDesc", "Personal Video Collection"); docXML.Save("Videos.xml");
}
}
static int Main(string[] args) { CreateAttribute(); return 0; }
}
From the above Videos.xml file, this code would result in: <Title Screenplay="Marty Kaplan">The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R <Title WrittenBy="Charlie Peter">Her Alibi Bruce Beresford 94 Mins DVD PG-13
C# 3.0 Practical Learning II
147
To support attribute addition, the XmlDocument class is equipped with the CreateAttribute() method, which is overloaded in three versions. The first version of this method has the following syntax: public XmlAttribute CreateAttribute(string name);
This method expects the name of the attribute as argument. If it succeeds, this method produces an XmlAttribute object. To add the new attribute to an element, you can call the XmlElement.SetAttributeNote() method. This method is overloaded in two versions. One of the versions uses the following syntax: public virtual XmlAttribute SetAttributeNode(XmlAttribute newAttr);
This method expects an XmlAttribute object. Here is an example that looks for a particular video in a collection and adds an ISBN attribute to it: using System; using System.IO; using System.Xml; namespace VideoCollection { public static class Exercise { private static void CreateAttribute() { string strFilename = "Videos.xml"; XmlDocument docXML = new XmlDocument(); if (File.Exists(strFilename)) { // Open the XML file docXML.Load(strFilename); // Create a new attribute XmlAttribute atrXML = docXML.CreateAttribute("ISBN"); atrXML.Value = "0-7907-3900-3"; // Get a list of elements whose names are Video XmlNodeList nodVideos = docXML.GetElementsByTagName("Video"); // Since we will look for a specific video, get the list of all titles XmlNodeList nodTitles = docXML.GetElementsByTagName("Title"); // Visit each title for (int i = 0; i < nodTitles.Count; i++) { // Look for a video whose title is "Her Alibi"
C# 3.0 Practical Learning II
148
if (nodTitles[i].InnerText.Equals("Her Alibi"))
{ // Once you find that video, add the new
attribute to it
((XmlElement) (nodVideos[i])).SetAttributeNode(atrXML); } } docXML.Save("Videos.xml"); }
} static int Main(string[] args) { CreateAttribute(); return 0; }
}
}
From the above Videos.xml file, this code would result in: <Title Screenplay="Marty Kaplan">The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R <Title WrittenBy="Charlie Peter">Her Alibi Bruce Beresford 94 Mins DVD PG-13
Practical Learning: Creating an Attribute 1. Create a new function as follows: using System; using System.IO; using System.Xml;
C# 3.0 Practical Learning II
149
namespace CountriesStatistics1 { public static class Program { private static void CreateContinent() { string strFilename = "continents.xml"; XmlDocument xmlDocContinents = new XmlDocument(); FileStream fsStatistics = null; if (File.Exists(strFilename)) { string strContinent = null; try {
d);
fsStatistics = new FileStream(strFilename, FileMode.Open, FileAccess.Rea // Open the XML file xmlDocContinents.Load(fsStatistics); } finally { fsStatistics.Close(); }
user
// Request the name of a continent from the Console.Write("Enter the name of a continent:
");
strContinent = Console.ReadLine(); // Create an element that the new attribute will
be added to
XmlElement xmlNewContinent =
xmlDocContinents.CreateElement("Continent"); // Create a Continent element and set its value to strContinent);
// that of the new continent xmlNewContinent.SetAttribute("Name", // Add the element and its attribute to the
document
xmlDocContinents.DocumentElement.AppendChild(xml
NewContinent); // Save the XML file xmlDocContinents.Save("continents.xml");
C# 3.0 Practical Learning II
150
} }
}
static int Main(string[] args) { CreateContinent(); return 0; }
}
2. Execute the application and create a continent. Here is an example: Enter the name of a continent: North America Press any key to continue . . .
3. Close the DOS window <World>
The Parent of an Attribute Once an attribute has been created, to identify the element it belongs to, you can access its XmlAttribute.OwnerElement property. This property produces an XmlElement value.
Attribute Removal If an element has an attribute you don't want or that you don't need anymore, you can delete that attribute. You have various options, two are available through the XmlElement class. The attributes of an XmlElement object are considered stored in an indexed list with the most left attribute at index 0, the second from left at index 1, and so on. Based on this, to remove an attribute by locating it based on its index, you can call the XmlElement.RemoveAt() method. Its syntax is: public virtual XmlNode RemoveAttributeAt(int i);
C# 3.0 Practical Learning II
151
When calling this method, if an attribute exists at position i, it will be deleted and the method would return it. If there is no attribute at that index, the method doesn't do anything and it returns 0. Using the XmlElement.RemoveAt() method to delete an attribute can be uncertain because you would not know whether there is an attribute at the specified position. An alternative is to specify the name of the attribute you want to delete. To support this, the XmlElement class is equipped with the RemoveAttribute() method, which is overloaded with two versions. One of the versions of this method uses the following syntax: public virtual void RemoveAttribute(string name);
This method expects as argument the name of the attribute to remove. Another technique you can use consists of defining an XmlAttribute object and submitting to its XmlElement parent to delete. To do this, you can call the RemoveAttributeNode() method of the XmlElement object. Its syntax is: public virtual XmlAttribute RemoveAttributeNode(XmlAttribute oldAttr);
When calling this method, pass the attribute object as argument. If the attribute exists, it would be removed and the method would return the deleted attribute. If the attribute doesn't exist, nothing would happen.
The Collection of Attributes of an Element Introduction So far, we have used only one attribute per element. Fortunately, you can create as many attributes as you judge necessary in an element. To do this, type the name of each attribute, assign it a double-quoted string and separate the attribute from the next with an empty space. Here is an example of an element with different attributes:
As mentioned already and as you should always remember, attributes belong to an element. To support them, the attributes of an element are stored in the Attributes property of the XmlElement class. The XmlElement.Attributes property is based on a class called XmlAttributeCollection. The XmlAttributeCollection class is based
C# 3.0 Practical Learning II
152
on the XmlNamedNodeMap class. This class lays a foundation to access attributes using their names or index in the collection. To know the number of attributes in an element, you can use the XmlNamedNodeMap.Count property.
Practical Learning: Adding Attributes 1. Create a new Console Application named CountriesStatistics2 2. To save the project, on the Standard toolbar, click the Save All button 3. Accept all defaults and click Save 4. In the Solution Explorer, right-click CountriesStatistics2 -> Add -> New Item... 5. In the Templates list, make sure XML File is selected. Set the Name to continents and click Add 6. Change the file as follows: <World Area="510,072,000,000" Population="6,379,157,361">
7. To save the file, on the main menu, click File -> Save continents.xml As... 8. Access the main folder of the current project and, inside of it, open a sub-folder of the same name (you should be in that folder already). In the sub-folder of the same name, open the bin sub-folder followed by the Release sub-folder. Click Save
Access to an Attribute C# 3.0 Practical Learning II
153
To access an attribute by its position in the collection, you can use the XmlNamedNodeMap.Item() method. The XmlAttributeCollection class is equipped with an ItemOf indexed property. This property is overloaded in three versions. The first version has the following syntax: public virtual XmlAttribute this[int i] {get;}
This property allows you to access an attribute by considering that the attributes are stored in an array. The first or most left attribute has an index of 0; the second attribute from left (of course without counting the name of the element) has an index of 1, and so on. It can be difficult and sometimes unpredictable, in some scenarios, to access an attribute by its index because you must know exactly where each attribute is positioned. Consider the following version of our Videos.xml XML file: <Title StoryBy="Marty Kaplan and Jonathan Reynold" Screenplay="Marty Kaplan">The Distinguished Gentleman Jonathan Lynn 112 Minutes DVD R <Title Screenplay="Charlie Peter">Her Alibi Bruce Beresford 94 Mins DVD PG-13
In the first video, the name of the screenplay writer is stored at index 1. In the second video, the name of the screenplay writer is stored at index 0. In this case, it may not be a good item to use the index to locate an attribute. Fortunately, the second version of the overloaded XmlAttributeCollection.ItemOf[] property has the following syntax: public virtual XmlAttribute this[string name] {get;}
With this version, you can explicitly specify the name of the attribute that you want.
C# 3.0 Practical Learning II
154
Practical Learning: Accessing an Attribute 1. To display the continents, change the code as follows: using System; using System.IO; using System.Xml; namespace CountriesStatistics2 { public static class Program { private static void ShowContinents() { string strFilename = "continents.xml"; XmlDocument xmlWorldStats = new XmlDocument(); FileStream fsWorldStats = null; if (File.Exists(strFilename)) { string strContinent = null; try {
d);
fsWorldStats = new FileStream(strFilename, FileMode.Open, FileAccess.Rea // Open the XML file xmlWorldStats.Load(fsWorldStats);
} finally { fsWorldStats.Close(); }
// Get a list of elements whose names are Continent t");
XmlNodeList lstContinents = xmlWorldStats.GetElementsByTagName("Continen // Show the statistics on the continents Console.WriteLine(" =-= Continents =-="); Console.WriteLine("Name\tArea\t\tPopulation");
ext);
foreach(XmlNode attr in lstContinents) { Console.WriteLine("{0}\t{1}\t{2}", attr.Attributes["Name"].InnerText, attr.Attributes["Area"].InnerText, attr.Attributes["Population"].InnerT }
C# 3.0 Practical Learning II
155
} }
}
public static int Main(string[] args) { ShowContinents(); return 0; }
}
2. Execute the application to see the result: =-= Continents =-= Name Area Africa 30,065,000 Europe 9,938,000
Population 807,419,000 730,916,000
3. Close the DOS window
Attribute Addition Whether using its index or name, after accessing an attribute, you can manipulate it as you see fit. For example, you can change or delete it using the same techniques we saw to perform on an individual attribute. As mentioned already, the attributes are stored as a list. Because you have complete access to this list and the positions of its attributes, when creating or adding a new attribute, you can specify the position the new attribute should have in the collection. To create an attribute as the first in an element, you can call the XmlAttributeCollection.Prepend() method. Its syntax is: public virtual XmlAttribute Prepend(XmlAttribute node);
Another technique you can use consists of locating an attribute first. Once you have one, to create a new attribute before it, you can call the XmlAttributeCollection.InsertBefore() method. Its syntax is: public virtual XmlAttribute InsertBefore(XmlAttribute newNode, XmlAttribute refNode);
To add a new attribute after the current one, you can call the XmlAttributeCollection.InsertAfter() method. Its syntax is: public virtual XmlAttribute InsertAfter(XmlAttribute newNode, XmlAttribute refNode);
To add an attribute at the end of the list of attributes of an element, you can call the XmlAttributeCollection.Append() method. Its syntax is:
C# 3.0 Practical Learning II
156
public virtual XmlAttribute Append(XmlAttribute node);
Practical Learning: Creating Attributes 1. To allow the user to create a new continent, change the program as follows: using System; using System.IO; using System.Xml; namespace CountriesStatistics2 { public static class Program { private static void ShowContinents() { string strFilename = "continents.xml"; XmlDocument xmlWorldStats = new XmlDocument(); FileStream fsWorldStats = null;
d);
if (File.Exists(strFilename)) { try { fsWorldStats = new FileStream(strFilename, FileMode.Open, FileAccess.Rea // Open the XML file xmlWorldStats.Load(fsWorldStats); } finally { fsWorldStats.Close(); }
Continent
// Get a list of elements whose names are XmlNodeList lstContinents = xmlWorldStats.GetElementsByTagName("Continen
t"); // Show the statistics on the continents Console.WriteLine("\n=========================== ========"); ======");
Console.WriteLine(" =-= Continents =-="); Console.WriteLine("============================= Console.WriteLine("Name\tArea\t\tPopulation");
======");
Console.WriteLine("============================= foreach (XmlNode attr in lstContinents)
C# 3.0 Practical Learning II
157
{ Console.WriteLine("{0}\t{1}\t{2}", attr.Attributes["Name"].InnerText, attr.Attributes["Area"].InnerText, attr.Attributes["Population"].InnerT ext);
Console.WriteLine("-------------------------
----------"); }
}
}
private static void CreateNewContinent() { string strContinent = null; string strArea = null; string strPopulation = null; // Open the XML file XmlDocument xmlDocContinents = new XmlDocument(); string strFilename = "continents.xml"; FileStream fsContinents = null; if (File.Exists(strFilename)) { try { fsContinents = new FileStream(strFilename, FileMode.Open, FileAccess.Rea d);
// Open the XML file xmlDocContinents.Load(fsContinents);
} finally { fsContinents.Close(); } }
// Create a Continent element that the new attribute will be added to XmlElement xmlNewContinent = xmlDocContinents.CreateElement("Continent"); // Present the current list of continents to the user
ShowContinents(); // Request the name of a continent from the user Console.Write("Enter a new continent: "); strContinent = Console.ReadLine();
C# 3.0 Practical Learning II
158
// Create a Name attribute using the continent that the user entered xmlNewContinent.SetAttribute("Name", strContinent); // Request the continent's area from the user Console.Write("Enter the area of the continent: "); strArea = Console.ReadLine(); // Create the Area attribute xmlNewContinent.SetAttribute("Area", strArea); // Request the population of the continent from the
user
Console.Write("Enter the population of the continent: "); strPopulation = Console.ReadLine(); // Create the Population attribute xmlNewContinent.SetAttribute("Population", strPopulation); // Add the element and its attribute to the document xmlDocContinents.DocumentElement.AppendChild(xmlNewC ontinent);
}
// Save the XML file xmlDocContinents.Save(strFilename); ShowContinents();
public static int Main(string[] args) { int choice = 0; Console.WriteLine(" =-= Main Menu =-="); Console.WriteLine("0 - Quit"); Console.WriteLine("1 - Display Continents"); Console.WriteLine("2 - Create New Continent"); Console.Write("Your Choice? "); choice = int.Parse(Console.ReadLine()); switch (choice) { case 1: ShowContinents(); break; case 2: CreateNewContinent(); break; } Console.WriteLine(); return 0; }
}
}
C# 3.0 Practical Learning II
159
2. Execute the application to test it. Here is an example: =-= Main Menu =-= 0 - Quit 1 - Display Continents 2 - Create New Continent Your Choice? 2 =================================== =-= Continents =-= =================================== Name Area Population =================================== Africa 30,065,000 807,419,000 ----------------------------------Europe 9,938,000 730,916,000 ----------------------------------Enter a new continent: North America Enter the area of the continent: 24490000 Enter the population of the continent: 514600000 =================================== =-= Continents =-= =================================== Name Area Population =================================== Africa 30,065,000 807,419,000 ----------------------------------Europe 9,938,000 730,916,000 ----------------------------------North America 24490000 514600000 ----------------------------------Press any key to continue . . .
3. Close the DOS window <World Area="510,072,000,000" Population="6,379,157,361">
C# 3.0 Practical Learning II
160
Capital="Rome" Code="it" />
4. To allow the user to create a new country, change the file as follows: using System; using System.IO; using System.Xml; namespace CountriesStatistics2 { public static class Program { private static void ShowContinents() { string strFilename = "continents.xml"; XmlDocument xmlWorldStats = new XmlDocument(); FileStream fsWorldStats = null;
d);
if (File.Exists(strFilename)) { try { fsWorldStats = new FileStream(strFilename, FileMode.Open, FileAccess.Rea // Open the XML file xmlWorldStats.Load(fsWorldStats); } finally { fsWorldStats.Close(); }
Continent
// Get a list of elements whose names are XmlNodeList lstContinents = xmlWorldStats.GetElementsByTagName("Continen
t"); // Show the statistics on the continents Console.WriteLine("\n=========================== ========"); ======");
Console.WriteLine(" =-= Continents =-="); Console.WriteLine("============================= Console.WriteLine("Name\tArea\t\tPopulation");
C# 3.0 Practical Learning II
161
Console.WriteLine("============================= ======");
foreach (XmlNode attr in lstContinents) { Console.WriteLine("{0}\t{1}\t{2}", attr.Attributes["Name"].InnerText, attr.Attributes["Area"].InnerText, attr.Attributes["Population"].InnerT
ext);
Console.WriteLine("-------------------------
----------"); }
}
} private static void CreateNewContinent() { string strContinent = null; string strArea = null; string strPopulation = null; // Open the XML file XmlDocument xmlDocContinents = new XmlDocument(); string strFilename = "continents.xml"; FileStream fsContinents = null; if (File.Exists(strFilename)) { try { fsContinents = new FileStream(strFilename, FileMode.Open, FileAccess.Rea d);
// Open the XML file xmlDocContinents.Load(fsContinents);
} finally { fsContinents.Close(); } }
// Create a Continent element that the new attribute will be added to XmlElement xmlNewContinent = xmlDocContinents.CreateElement("Continent"); // Present the current list of continents to the user
ShowContinents(); // Request the name of a continent from the user Console.Write("Enter a new continent: ");
C# 3.0 Practical Learning II
162
strContinent = Console.ReadLine(); // Create a Name attribute using the continent that the user entered xmlNewContinent.SetAttribute("Name", strContinent); // Request the continent's area from the user Console.Write("Enter the area of the continent: "); strArea = Console.ReadLine(); // Create the Area attribute xmlNewContinent.SetAttribute("Area", strArea); // Request the population of the continent from the
user
Console.Write("Enter the population of the continent: "); strPopulation = Console.ReadLine(); // Create the Population attribute xmlNewContinent.SetAttribute("Population", strPopulation); // Add the element and its attribute to the document xmlDocContinents.DocumentElement.AppendChild(xmlNewC ontinent);
}
// Save the XML file xmlDocContinents.Save(strFilename); ShowContinents();
private static void AddCountry() { string strContinent = null; string strCountry = null; string strArea = null; string strPopulation = null; string strCapital = null; string strCode = null; string strFilename = "continents.xml"; // Open the XML file XmlDocument xmlDocContinents = new XmlDocument(); FileStream fsContinents = null; if (File.Exists(strFilename)) { try { fsContinents = new FileStream(strFilename, FileMode.Open, FileAccess.Rea d);
// Open the XML file xmlDocContinents.Load(fsContinents);
C# 3.0 Practical Learning II
163
} finally { fsContinents.Close(); } } // Display the list of continents to the user Console.WriteLine("Here is a list of the created continents"); ShowContinents(); // Request a continent from the user Console.Write("Enter the desired continent: "); strContinent = Console.ReadLine(); // Get a list of elements whose names are Continent XmlNodeList lstContinents = xmlDocContinents.GetElementsByTagName("Continent"); // Visit each Continent element for (int i = 0; i < lstContinents.Count; i++) { // Get a list of the attributes of the current element
strContinent)
XmlAttributeCollection curAttributes = lstContinents[i].Attributes; // Check each attribute, looking for // the continent that the user entered for (int j = 0; j < curAttributes.Count; j++) { // Check if the current continent // is the same that the user selected if (curAttributes["Name"].InnerText == {
reference
// Once you find one, get its XmlElement XmlElement elmNewCountry =
xmlDocContinents.CreateElement("Country"); // Request the name of a country from the user country: "); user , strCountry);
Console.Write("Enter the name of the strCountry = Console.ReadLine(); // Create the country specified by the elmNewCountry.SetAttribute("CountryName" // Request the area of the country from
the user
C# 3.0 Practical Learning II
164
Console.Write("Enter the area of the country: ");
strArea = Console.ReadLine(); // Create the Area specified by the user elmNewCountry.SetAttribute("Area",
strArea); // Request the population of the country
from the user
Console.Write("Enter the population of
the country: ");
strPopulation = Console.ReadLine(); // Create the Population attribute elmNewCountry.SetAttribute("Population",
strPopulation);
// Request the Capital of the country from the user
Console.Write("Enter the capital of the
country: ");
strCapital = Console.ReadLine(); // Create the Capital attribute elmNewCountry.SetAttribute("Capital",
strCapital);
country from the user
// Request the Internet Code of the
Console.Write("Enter the Internet Code of
the country: ");
strCode = Console.ReadLine(); // Create the Internet Code attribute elmNewCountry.SetAttribute("Code",
strCode);
// Add the element (and its attribute) as
// a child of the current Continent lstContinents[i].AppendChild(elmNewCount
ry);
// Save the XML file xmlDocContinents.Save("Countries.xml"); } }
break;
}
} public static int Main(string[] args) { int choice = 0;
C# 3.0 Practical Learning II
165
do {
Console.WriteLine(" =-= Main Menu =-="); Console.WriteLine("1 - Display Continents"); Console.WriteLine("2 - Create New Continent"); Console.WriteLine("3 - Create New Country"); Console.WriteLine("0 - Quit"); Console.Write("Your Choice? "); choice = int.Parse(Console.ReadLine());
switch (choice) { case 1: ShowContinents(); break; case 2: CreateNewContinent(); break; case 3: AddCountry(); break; default: break; } } while ((choice == 1) || (choice == 2) || (choice == 3));
} }
Console.WriteLine(); return 0;
}
5. Execute the application to test it. Here is an example: =-= Main Menu =-= 1 - Display Continents 2 - Create New Continent 3 - Create New Country 0 - Quit Your Choice? 2 =================================== =-= Continents =-= =================================== Name Area Population =================================== Africa 30,065,000 807,419,000 ----------------------------------Europe 9,938,000 730,916,000 ----------------------------------North America 24490000 514600000 ----------------------------------Enter a new continent: Asia
C# 3.0 Practical Learning II
166
Enter the area of the continent: 43810582 Enter the population of the continent: 3902404193 =================================== =-= Continents =-= =================================== Name Area Population =================================== Africa 30,065,000 807,419,000 ----------------------------------Europe 9,938,000 730,916,000 ----------------------------------North America 24490000 514600000 ----------------------------------Asia 43810582 3902404193 ----------------------------------=-= Main Menu =-= 1 - Display Continents 2 - Create New Continent 3 - Create New Country 0 - Quit Your Choice? 3 Here is a list of the created continents =================================== =-= Continents =-= =================================== Name Area Population =================================== Africa 30,065,000 807,419,000 ----------------------------------Europe 9,938,000 730,916,000 ----------------------------------North America 24490000 514600000 ----------------------------------Asia 43810582 3902404193 ----------------------------------Enter the desired continent: Europe Enter the name of the country: Italy Enter the area of the country: 301230 Enter the population of the country: 58751711 Enter the capital of the country: Rome Enter the Internet code of the country: it =-= Main Menu =-= 1 - Display Continents 2 - Create New Continent 3 - Create New Country 0 - Quit Your Choice? 0 Press any key to continue . . .
6. Close the DOS window
C# 3.0 Practical Learning II
167
<World Area="510,072,000,000" Population="6,379,157,361">
Attribute Removal Using the list of attributes of an element, you can delete one or all attributes of an element. Since the attributes are stored in a collection, you can locate the undesired attribute by its index and then delete it. To do this, you can call the XmlAttributeCollection.RemoveAt() method. Its syntax is: public virtual XmlAttribute RemoveAt(int i);
This method expects the index of the attribute that needs to be removed. As mentioned for the XmlAttributeCollection.ItemOf indexed property, to efficiently use this RemoveAt() method, you should know the exact index of the attribute, otherwise, you may access and therefore delete the wrong attribute. An alternative is to explicitly identify the attribute you want to delete. To do this, you can call the XmlAttributeCollection.Remove() method. Its syntax is: public virtual XmlAttribute Remove(XmlAttribute node);
This method takes as attribute the XmlAttribute identification of the attribute you want to remove. To
delete
all
attributes
of
an
element,
you
can
call
the
XmlAttributeCollection.RemoveAll() method. Its syntax is: public virtual void RemoveAll();
C# 3.0 Practical Learning II
168
This method would simply remove all attributes that belong to an XmlElement object.
C# 3.0 Practical Learning II
169
Characteristics of XML Nodes Overview of Types of Nodes Introduction To differentiate the various nodes that belong to an XML file, they are classified by their category. As mentioned earlier, the types of node are listed in the XmlNodeType enumerator.
Comments A comment is a character, a line or a paragraph that is not considered as part of the XML code that needs to be processed. A comment allows you to insert notes or personal observations inside an XML file. For this reason, a commented section can be written any way you like. This means that a comment can include plain text, formulas, expressions, or even XML code as long as you know that that XML code will not be validated: it will ignored by the parser.
To create a comment, you use the following formula: