XPathNavigator SetValue wipes out XmlType

G

Guest

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.

-- TestXPathNavBugSchemaBase.xsd --
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mine="http://mytest.ca/mine" targetNamespace="http://mytest.ca/mine"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:complexType name="OrderBase">
<xs:annotation>
<xs:documentation>Base Schema for Orders</xs:documentation>
</xs:annotation>
<xs:attribute name="Name" type="xs:string" use="required"/>
<xs:attribute name="Updatable" type="xs:boolean" use="required"
fixed="true"/>
</xs:complexType>
<xs:complexType name="PurchaseOrderBase">
<xs:complexContent>
<xs:extension base="mine:OrderBase">
<xs:attribute name="PurchaseOrderNumber" type="xs:string" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="OrderItemBase">
<xs:annotation>
<xs:documentation>Base Schema for Order items</xs:documentation>
</xs:annotation>
<xs:attribute name="ItemType" type="xs:string" use="required"/>
<xs:attribute name="ItemDescription" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="PurchaseOrderItemBase">
<xs:complexContent>
<xs:extension base="mine:OrderItemBase">
<xs:attribute name="PurchaseOrderNumber" type="xs:string" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>


-- TestXPathNavBugSchema.xsd --
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mine="http://mytest.ca/mine" targetNamespace="http://mytest.ca/mine"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="TestXPathNavBugSchemaBase.xsd"/>
<xs:complexType name="AutoPartsPurchaseOrderType">
<xs:complexContent>
<xs:extension base="mine:purchaseOrderBase">
<xs:sequence>
<xs:element name="Header" type="mine:purchaseOrderItemBase"/>
<xs:element name="Body" type="mine:purchaseOrderItemBase"/>
<xs:element name="Footer" type="mine:purchaseOrderItemBase"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="AutoPartsPurchaseContract">
<xs:complexType>
<xs:sequence>
<xs:element name="PurchaseOrders" type="mine:AutoPartsPurchaseOrderType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

-- TestXPathNavBug.xml --
<?xml version="1.0" encoding="UTF-8"?>
<AutoPartsPurchaseContract xmlns="http://mytest.ca/mine"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mytest.ca/mine TestXPathNavBugSchema.xsd">
<PurchaseOrders Updatable="true" Name="" PurchaseOrderNumber="">
<Header ItemType="" ItemDescription="" PurchaseOrderNumber="" />
<Body ItemType="" ItemDescription="" PurchaseOrderNumber="" />
<Footer ItemType="" ItemDescription="" PurchaseOrderNumber="" />
</PurchaseOrders>
</AutoPartsPurchaseContract>

-- Program.cs --
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Schema;

namespace TestXPathNavBug
{
class Program
{
static void Main(string[] args)
{
const string xmlFileName = @"..\..\TestXPathNavBug.xml";

//Load the xml with its xsd
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://mytest.ca/mine",
@"..\..\TestXPathNavBugSchema.xsd");
settings.ValidationType = ValidationType.Schema;

XmlReader reader = XmlReader.Create(xmlFileName, settings);

XmlDocument doc = new XmlDocument();
doc.Load(reader);

//Create an XPathNavigator
XPathNavigator xpath = doc.CreateNavigator();

// Start at the top
xpath.MoveToRoot();


//Modify the xml document
TraverseTree(xpath);

//Save
reader.Close();
doc.Save(xmlFileName);

Console.ReadKey();
}

private static void TraverseTree(XPathNavigator xpath)
{
//Process this node
if (xpath.NodeType == XPathNodeType.Element)
{
Console.WriteLine("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.IsNullOrEmpty(xmlType.Name))
Console.WriteLine(" XmlType: {0}", xmlType.Name);

xmlBaseType = xmlType.BaseXmlSchemaType;
if (!string.IsNullOrEmpty(xmlBaseType.Name))
Console.WriteLine(" XmlBaseType: {0}",
xmlBaseType.Name);
}

//These are the attributes we want to populate in the XML
file.
if (xmlBaseType != null
&& !string.IsNullOrEmpty(xmlBaseType.Name)
&& xmlBaseType.Name.Equals("OrderItemBase",
StringComparison.OrdinalIgnoreCase))
{
if (xpath.HasAttributes)
{
//Grab a clone to start navigating at this position
XPathNavigator navAttributes = xpath.Clone();

navAttributes.MoveToFirstAttribute();

do
{
Console.WriteLine(" Attribute: {0}, can edit?
{1}", navAttributes.Name, navAttributes.CanEdit);

string valueToSave = string.Empty;
switch (navAttributes.Name.ToLowerInvariant())
{
case "itemtype":
valueToSave = string.Format("{0}{1}",
navAttributes.Name, xmlType.Name);
break;

case "itemdescription":
valueToSave = string.Format("Describe
{0}{1}", navAttributes.Name, xmlType.Name);
break;

case "purchaseordernumber":
valueToSave =
DateTime.Now.Ticks.ToString();
break;
}

//TODO: This reproduces the bug.
/* If you call the SetValue, then the XmlTypes
are wiped out on
* subsequent Moves.
* */
if (!string.IsNullOrEmpty(valueToSave))
navAttributes.SetValue(valueToSave);

} while (navAttributes.MoveToNextAttribute());

}
}
}

//Go down the branch
if (xpath.HasChildren)
{
xpath.MoveToFirstChild();

do
{
TraverseTree(xpath);
} while (xpath.MoveToNext());

//Go back to the top of the branch
xpath.MoveToParent();
}


}
}
}
 
W

Walter Wang [MSFT]

Hi Noremac,

Please see following document:

#Modify XML Data using XPathNavigator
http://msdn2.microsoft.com/en-us/library/zx28tfx1(VS.80).aspx
Specifically, if the child elements or attributes of an element are
inserted, updated, or deleted, then the validity of the element becomes
unknown. This is represented by the Validity property of the element's
SchemaInfo property being set to NotKnown. Furthermore, this effect
cascades upwards recursively across the XML document, because the validity
of the element's parent element (and its parent element, and so on) also
becomes unknown.



When you changed the first element's attributes, its SchemaInfo.Validity
becomes NotKnown; and the XmlType will need Validity with Valid value to
return the correct type.

To fix this, you need to call XmlDocument.Validate again after you changed
the element's attributes.


Hope this helps.


Sincerely,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express, please make sure you clear the
check box "Tools/Options/Read: Get 300 headers at a time" to see your reply
promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top