XmlReader skips half data sent to webservice
I have a web service that has one method:
[WebMethod]
public bool SyncUserData(string userxml)
The xml is a series of user records and I use an XmlReader to read through the data and process it.
When I call the web service with 2000 records, it processes 2000 records. When my client calls it with the same xml, it processes 1000 records. It processes every other record.
Does anyone have any experience with this sort of problem? My thought is that it is an encoding issue but I have tried sending the data to the service as ASCII, ISO-8859-1 etc in my tests and cannot recreate.
Any help much appreciated.
This is the calling code:
while (u开发者_C百科serXml.Read())
{
if (userXml.Name == NODE_NAME_FILE_NAME && userXml.NodeType == XmlNodeType.Element)
{
_importFilename = userXml.ReadString();
}
if (userXml.Name == NODE_NAME_USER && userXml.NodeType == XmlNodeType.Element)
{
ProcessUser(userXml);
}
}
and this is what processUser does with teh xml reader
private void ProcessUser(XmlReader userXml)
{
_usersinfeed++;
XmlDocument user = new XmlDocument();
user.LoadXml(userXml.ReadOuterXml());
...
}
What's biting you is the side-effect of ReadOuterXml
- it most likely advances the current position of the XmlReader - but then, in your loop while (userXml.Read())
you advance it again - skipping one xml element in the process.
There are various ways of solving this - but the easiest and cleanest would be to not use XmlReader
. Is that an option?
An easier way to process xml is Linq to Xml:
public static void Main()
{
SyncUserData(@"
<doc>
<filename>test</filename>
<user>Someone</user>
<user>Someone2</user>
<filename>testA</filename>
<user>Someone else</user>
<user>Someone else2</user>
</doc>
");
}
const string NODE_NAME_FILE_NAME = "filename";
const string NODE_NAME_USER = "user";
static string _importFilename;
static int _usersinfeed;
public static bool SyncUserData(string userxml) {
foreach(XElement el in XDocument.Parse(userxml).Descendants()) {
//or: XDocument.Parse(userxml).Root.Elements() -- this depends on your document
if (el.Name == NODE_NAME_FILE_NAME)
_importFilename = el.Value;
if (el.Name == NODE_NAME_USER)
ProcessUser(el);
}
return true;
}
private static void ProcessUser(XElement el)
{
_usersinfeed++;
Console.WriteLine("User:{0}, file:{1}\n{2}\n",_usersinfeed,_importFilename,el);
//you probably don't need the following anymore
//XmlDocument user = new XmlDocument();
//user.LoadXml(el.CreateReader());
//...
}
Which outputs:
User:1, file:test
<user>Someone</user>
User:2, file:test
<user>Someone2</user>
User:3, file:testA
<user>Someone else</user>
User:4, file:testA
<user>Someone else2</user>
However, you may be able to use XML Serialization - that's a very easy way to parse/generate XML without much boilerplate at all also gives you a .NET native datastructure to work with to boot! Then, you just need a small set of classes to define the document structure, and the framework can create instances auto-magically from XML for you, without any manual parsing code whatsoever. Not all XML syntaxes are amenable to that, however.
精彩评论