Hi.
Using VS2005, .NET 2.0.
I have an xml document that I want to go through and set the values on
attributes of elements. The elements are complex types defined in my schema
(xsd) files.
I can iterate the document and get my XmlType and XmlBaseType values just
fine. However, as soon as I call SetValue to write to an attribute, the
XmlType is always null so I can no longer test the rest of the elements in
the document.
Following are the Xsd, Xml and Program.cs to recreate the problem.
-- TestXPathNavBug SchemaBase.xsd --
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mine="htt p://mytest.ca/mine" targetNamespace ="http://mytest.ca/mine"
elementFormDefa ult="qualified" attributeFormDe fault="unqualif ied">
<xs:complexTy pe name="OrderBase ">
<xs:annotatio n>
<xs:documentati on>Base Schema for Orders</xs:documentatio n>
</xs:annotation>
<xs:attribute name="Name" type="xs:string " use="required"/>
<xs:attribute name="Updatable " type="xs:boolea n" use="required"
fixed="true"/>
</xs:complexType>
<xs:complexTy pe name="PurchaseO rderBase">
<xs:complexCont ent>
<xs:extension base="mine:Orde rBase">
<xs:attribute name="PurchaseO rderNumber" type="xs:string " use="required"/>
</xs:extension>
</xs:complexConte nt>
</xs:complexType>
<xs:complexTy pe name="OrderItem Base">
<xs:annotatio n>
<xs:documentati on>Base Schema for Order items</xs:documentatio n>
</xs:annotation>
<xs:attribute name="ItemType" type="xs:string " use="required"/>
<xs:attribute name="ItemDescr iption" type="xs:string " use="required"/>
</xs:complexType>
<xs:complexTy pe name="PurchaseO rderItemBase">
<xs:complexCont ent>
<xs:extension base="mine:Orde rItemBase">
<xs:attribute name="PurchaseO rderNumber" type="xs:string " use="required"/>
</xs:extension>
</xs:complexConte nt>
</xs:complexType>
</xs:schema>
-- TestXPathNavBug Schema.xsd --
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mine="htt p://mytest.ca/mine" targetNamespace ="http://mytest.ca/mine"
elementFormDefa ult="qualified" attributeFormDe fault="unqualif ied">
<xs:include schemaLocation= "TestXPathNavBu gSchemaBase.xsd "/>
<xs:complexTy pe name="AutoParts PurchaseOrderTy pe">
<xs:complexCont ent>
<xs:extension base="mine:Purc haseOrderBase">
<xs:sequence>
<xs:element name="Header" type="mine:Purc haseOrderItemBa se"/>
<xs:element name="Body" type="mine:Purc haseOrderItemBa se"/>
<xs:element name="Footer" type="mine:Purc haseOrderItemBa se"/>
</xs:sequence>
</xs:extension>
</xs:complexConte nt>
</xs:complexType>
<xs:element name="AutoParts PurchaseContrac t">
<xs:complexType >
<xs:sequence>
<xs:element name="PurchaseO rders" type="mine:Auto PartsPurchaseOr derType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
-- TestXPathNavBug .xml --
<?xml version="1.0" encoding="UTF-8"?>
<AutoPartsPurch aseContract xmlns="http://mytest.ca/mine"
xmlns:xsi="http ://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocat ion="http://mytest.ca/mine TestXPathNavBug Schema.xsd">
<PurchaseOrde rs Updatable="true " Name="" PurchaseOrderNu mber="">
<Header ItemType="" ItemDescription ="" PurchaseOrderNu mber="" />
<Body ItemType="" ItemDescription ="" PurchaseOrderNu mber="" />
<Footer ItemType="" ItemDescription ="" PurchaseOrderNu mber="" />
</PurchaseOrders>
</AutoPartsPurcha seContract>
-- Program.cs --
using System;
using System.Collecti ons.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPat h;
using System.Xml.Sche ma;
namespace TestXPathNavBug
{
class Program
{
static void Main(string[] args)
{
const string xmlFileName = @"..\..\TestXPa thNavBug.xml";
//Load the xml with its xsd
XmlReaderSettin gs settings = new XmlReaderSettin gs();
settings.Schema s.Add("http://mytest.ca/mine",
@"..\..\TestXPa thNavBugSchema. xsd");
settings.Valida tionType = ValidationType. Schema;
XmlReader reader = XmlReader.Creat e(xmlFileName, settings);
XmlDocument doc = new XmlDocument();
doc.Load(reader );
//Create an XPathNavigator
XPathNavigator xpath = doc.CreateNavig ator();
// Start at the top
xpath.MoveToRoo t();
//Modify the xml document
TraverseTree(xp ath);
//Save
reader.Close();
doc.Save(xmlFil eName);
Console.ReadKey ();
}
private static void TraverseTree(XP athNavigator xpath)
{
//Process this node
if (xpath.NodeType == XPathNodeType.E lement)
{
Console.WriteLi ne("Element: {0}", xpath.Name);
//See if this is one of our schema types
XmlSchemaType xmlBaseType = null;
XmlSchemaType xmlType = xpath.XmlType;
if (xmlType != null)
{
if (!string.IsNull OrEmpty(xmlType .Name))
Console.WriteLi ne(" XmlType: {0}", xmlType.Name);
xmlBaseType = xmlType.BaseXml SchemaType;
if (!string.IsNull OrEmpty(xmlBase Type.Name))
Console.WriteLi ne(" XmlBaseType: {0}",
xmlBaseType.Nam e);
}
//These are the attributes we want to populate in the XML
file.
if (xmlBaseType != null
&& !string.IsNullO rEmpty(xmlBaseT ype.Name)
&& xmlBaseType.Nam e.Equals("Order ItemBase",
StringCompariso n.OrdinalIgnore Case))
{
if (xpath.HasAttri butes)
{
//Grab a clone to start navigating at this position
XPathNavigator navAttributes = xpath.Clone();
navAttributes.M oveToFirstAttri bute();
do
{
Console.WriteLi ne(" Attribute: {0}, can edit?
{1}", navAttributes.N ame, navAttributes.C anEdit);
string valueToSave = string.Empty;
switch (navAttributes. Name.ToLowerInv ariant())
{
case "itemtype":
valueToSave = string.Format(" {0}{1}",
navAttributes.N ame, xmlType.Name);
break;
case "itemdescriptio n":
valueToSave = string.Format(" Describe
{0}{1}", navAttributes.N ame, xmlType.Name);
break;
case "purchaseordern umber":
valueToSave =
DateTime.Now.Ti cks.ToString();
break;
}
//TODO: This reproduces the bug.
/* If you call the SetValue, then the XmlTypes
are wiped out on
* subsequent Moves.
* */
if (!string.IsNull OrEmpty(valueTo Save))
navAttributes.S etValue(valueTo Save);
} while (navAttributes. MoveToNextAttri bute());
}
}
}
//Go down the branch
if (xpath.HasChild ren)
{
xpath.MoveToFir stChild();
do
{
TraverseTree(xp ath);
} while (xpath.MoveToNe xt());
//Go back to the top of the branch
xpath.MoveToPar ent();
}
}
}
}