I am attempting to read a XML document containing elements like the data mentioned below.
Accessing the text node via reader.Value
, reader.ReadContentAsString()
, reader.ReadContentAsObject()
results in the value read being truncated to the last ampersand, so in the case of the data below that would be ISO^urn:ihe:iti:xds:2013:referral. Using XmlDocument
the text nodes can be read properly so I am assuming there has to be a way to make this work using the reader as well.
<Slot name="urn:ihe:iti:xds:2013:referenceIdList">
<ValueList>
<Value>123456^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral</Value>
<Value>098765^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral</Value>
</ValueList>
</Slot>
After asking the question I was able to determine my issue came from creating an XmlReader
from a XPathNavigator
instance created from a MessageBuffer
executing in the context of a WCF service call. Thus @DarkGray's answer was correct for the original question but did not really address the root of the problem. I provided a second answer which addressed my corner case.
System.ServiceModel.Channels.Message message; // the inbound SOAP message var buffer = message.CreateBufferedCopy(11 * 1024 * 1024); var navigator = buffer.CreateNavigator(); var reader = navigator.ReadSubtree(); // advance the reader to the text element // // `reader.Value` now produces ISO^urn:ihe:iti:xds:2013:referral
Answer: reader.Value
Output:
123456^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral
098765^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral
Example:
public static void Execute()
{
var xml = @"
<Slot name='urn:ihe:iti:xds:2013:referenceIdList'>
<ValueList>
<Value>123456^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral</Value>
<Value>098765^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral</Value>
</ValueList>
</Slot>
";
var reader = System.Xml.XmlReader.Create(new System.IO.StringReader(xml));
for (; ; )
{
if (!reader.Read())
break;
if (reader.NodeType == System.Xml.XmlNodeType.Text)
Console.WriteLine(reader.Value);
}
}
My question ended up being too broad as the incorrect behavior (truncation when using reader.Value
) only manifest when the code was executing within the context of a WCF call. It worked perfectly fine when exercising the logic of the containing class from a unit test.
So the salient setup can be reproduced as follows
The Failing Code
System.ServiceModel.Channels.Message message; // the inbound SOAP message
var buffer = message.CreateBufferedCopy(11 * 1024 * 1024);
var navigator = buffer.CreateNavigator();
var reader = navigator.ReadSubtree();
// advance the reader to the text element
//
// `reader.Value` now produces ISO^urn:ihe:iti:xds:2013:referral
Once this reader instance was created then any XmlText node read from it produced the truncated value when the text contained an character entity reference. The only way I found that allow for the original value to be read in high-fidelity was to eschew the use of the XPathNavigator completely and instead take the hit of creating another Message
instance. Note, the fix uses the long way around to write the SOAP envelope to the stream as affected service is using MTOM encoding. Writing to the stream directly from the MessageBuffer resulted in the MIME fences being written out.
The Fix
System.ServiceModel.Channels.Message message; // the inbound SOAP
var buffer = message.CreateBufferedCopy(MaxMessageSize);
var message = buffer.CreateMessage();
using (MemoryStream stream = new MemoryStream())
using (XmlWriter writer = XmlWriter.Create(stream))
{
message.WriteMessage(writer);
writer.Flush();
stream.Position = 0;
using (XmlReader reader = XmlReader.Create(stream))
{
// business logic goes here
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.