Discussion:
XmlLite issue - IXmlReader::IsEmptyElement()
(too old to reply)
d***@gmail.com
2008-01-31 15:11:54 UTC
Permalink
Hello

I'm working on a product that is using XmlLite. Following the example
given by Microsoft on their website (http://msdn2.microsoft.com/en-us/
library/ms753116(VS.85).aspx) I have made a while loop that calls
IXmlReader::Read() and switches on the nodeType gotten. In the
example, they use IXmlReader::IsEmptyElement() to determine if a node
looks like this:

<nodeName attributeName="attributeValue" />

As I am walking through a hierarchical XML, I need to know when a node
ends. So I have both that call to IXmlReader::IsEmptyElement() and
code in the case for XmlNodeType_EndElement that walks me back up to
the parent.

Unfortunately, I am not seeing IXmlReader::IsEmptyElement() returning
true ever. The node it is reading in my testing is this:

<parameterType name="stringParameter" type="string"
multiValued="false" />

And the code reading that node is effectively this:

while(S_OK == (hr = xmlReader->Read(&nodeType)))
{
switch(nodeType)
{
case XmlNodeType_Element:
{
if(FAILED(hr = xmlReader->GetLocalName(&nodeName, NULL)))
// ... error handling

// ... do stuff with the node

while(true)
{
if(FAILED(hr = reader->MoveToNextAttribute()))
// ... error handling

if(S_FALSE == hr)
break;

if(FAILED(hr = reader->GetLocalName(&attributeName, NULL)))
// ... error handling

if(FAILED(hr = reader->GetValue(&attributeValue, NULL)))
// ... error handling

// ... do stuff with the attribute
}

// ... I never see this return true, even on the node example
above
if(! xmlReader->IsEmptyElement())
// ... walk down the hierarchical tree of data

// ... note that I expect to stay put (not walk down) if the
element is empty
}
break;
case XmlNodeType_EndElement:
{
// ... walk up the hierarchical tree of data
}
break;

// ...

If anyone has used IXmlReader::IsEmptyElement successfully, can you
please tell me what you did to make it work? Or, if anyone else has
encountered the same problem, I would be encouraged to hear that,
because then I wouldn't feel so bad kludging the hierarchical logic.
d***@gmail.com
2008-01-31 15:26:19 UTC
Permalink
Post by d***@gmail.com
Hello
I'm working on a product that is using XmlLite. Following the example
given by Microsoft on their website (http://msdn2.microsoft.com/en-us/
library/ms753116(VS.85).aspx) I have made a while loop that calls
IXmlReader::Read() and switches on the nodeType gotten. In the
example, they use IXmlReader::IsEmptyElement() to determine if a node
<nodeName attributeName="attributeValue" />
As I am walking through a hierarchical XML, I need to know when a node
ends. So I have both that call to IXmlReader::IsEmptyElement() and
code in the case for XmlNodeType_EndElement that walks me back up to
the parent.
Unfortunately, I am not seeing IXmlReader::IsEmptyElement() returning
<parameterType name="stringParameter" type="string"
multiValued="false" />
while(S_OK == (hr = xmlReader->Read(&nodeType)))
{
switch(nodeType)
{
{
if(FAILED(hr = xmlReader->GetLocalName(&nodeName, NULL)))
// ... error handling
// ... do stuff with the node
while(true)
{
if(FAILED(hr = reader->MoveToNextAttribute()))
// ... error handling
if(S_FALSE == hr)
break;
if(FAILED(hr = reader->GetLocalName(&attributeName, NULL)))
// ... error handling
if(FAILED(hr = reader->GetValue(&attributeValue, NULL)))
// ... error handling
// ... do stuff with the attribute
}
// ... I never see this return true, even on the node example
above
if(! xmlReader->IsEmptyElement())
// ... walk down the hierarchical tree of data
// ... note that I expect to stay put (not walk down) if the
element is empty
}
break;
{
// ... walk up the hierarchical tree of data
}
break;
// ...
If anyone has used IXmlReader::IsEmptyElement successfully, can you
please tell me what you did to make it work? Or, if anyone else has
encountered the same problem, I would be encouraged to hear that,
because then I wouldn't feel so bad kludging the hierarchical logic.
Hi again

I have discovered the problem. The IXmlReader loses its state about
the element once you go read stuff about the attributes. The example
code provided by Microsoft (http://msdn2.microsoft.com/en-us/library/
ms753116(VS.85).aspx) is incorrect. You need to check
IsEmptyElement() before doing any work with the attributes. I am
posting this to hopefully help anyone who comes along with the same
problem later on. I now have this, and it works fine:

while(S_OK == (hr = xmlReader->Read(&nodeType)))
{
switch(nodeType)
{
case XmlNodeType_Element:
{
// ******************** new boolean to save the state
isEmptyElement = xmlReader->IsEmptyElement();

if(FAILED(hr = xmlReader->GetLocalName(&nodeName, NULL)))
// ... error handling

// ... do stuff with the node

while(true)
{
if(FAILED(hr = reader->MoveToNextAttribute()))
// ... error handling

if(S_FALSE == hr)
break;

if(FAILED(hr = reader->GetLocalName(&localAttributeName, NULL)))
// ... error handling

if(FAILED(hr = reader->GetValue(&value, NULL)))
// ... error handling

// ... do stuff with the attribute
}

// ******************** check my saved state rather than asking
the reader
if(! isEmptyElement)
// ... walk down the heirarchical tree of data

// ... note that I expect to stay put (not walk down) if the
element is empty
}
break;
case XmlNodeType_EndElement:
{
// ... walk up the hierarchical tree of data
}
break;

// ...

I find this behavior tremendously annoying, but at least I was able to
get things working.
Martin Honnen
2008-01-31 17:15:13 UTC
Permalink
Post by d***@gmail.com
I have discovered the problem. The IXmlReader loses its state about
the element once you go read stuff about the attributes. The example
code provided by Microsoft (http://msdn2.microsoft.com/en-us/library/
ms753116(VS.85).aspx) is incorrect. You need to check
IsEmptyElement() before doing any work with the attributes.
Or you can cosume the attributes first but then you need to call
pReader->MoveToElement();
before you check IsEmptyElement().
--
Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
a***@gmail.com
2008-02-07 16:29:38 UTC
Permalink
I have another problem with XmlLite losing it's state.
<TTAG>&#x10</TTAG>
I have an XML file where illegal data was entered. (The value of
&#x10 ). Whenever the parser gets to that line it returns S_FALSE
as a result, and then I can never seem to get it so sync up with
another line.

How can I handle this error gracefully and not just bail out?

AlanC
Martin Honnen
2008-02-07 17:06:17 UTC
Permalink
Post by a***@gmail.com
I have another problem with XmlLite losing it's state.
<TTAG>&#x10</TTAG>
I have an XML file where illegal data was entered. (The value of
&#x10 ). Whenever the parser gets to that line it returns S_FALSE
as a result, and then I can never seem to get it so sync up with
another line.
How can I handle this error gracefully and not just bail out?
x10 is not an allowed character in XML 1.0 so an XML parser has to
report that as a well-formedness error and stop parsing. I don't think
XmlLite has a setting to change that.

With XmlReader in the .NET framework you can use CheckCharacters on
XmlReaderSettings e.g.

XmlReaderSettings settings = new XmlReaderSettings();
settings.CheckCharacters = false;

string xml = @"<foo>&#x10;</foo>";

using (XmlReader reader = XmlReader.Create(new StringReader(xml),
settings))
{
while (reader.Read())
{
if (reader.HasValue)
{
Console.WriteLine("Value is \"{0}\"", reader.Value);
}
}
}

That way character _references_ to characters outside of the allowed
range are not causing an error but literal characters still do.
--
Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
Loading...