[英]How to read the text element of an XML node without dereferencing entities using XmlReader
我试图读取一个XML文档,其中包含类似下面提到的数据的元素。
通过reader.Value
, reader.ReadContentAsString()
, reader.ReadContentAsObject()
访问文本节点会导致读取的值被截断为最后一个与号,因此在以下数据的情况下为ISO ^ urn:ihe:iti :XDS:2013:转诊。 使用XmlDocument
可以正确读取文本节点,因此我假设也必须有一种使用阅读器进行此项工作的方法。
<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>
提出问题后,我能够确定我的问题来自从XPathNavigator
实例创建XmlReader
,该实例是从在WCF服务调用的上下文中执行的MessageBuffer
创建的。 因此,@ DarkGray的答案对于原始问题是正确的,但并未真正解决问题的根源。 我提供了第二个答案,解决了我的极端情况。
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
答: reader.Value
输出:
123456^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral
098765^^^&orgID&ISO^urn:ihe:iti:xds:2013:referral
例:
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);
}
}
我的问题最终变得太广泛了,因为不正确的行为(使用reader.Value
时被截断)仅在WCF调用的上下文中执行代码时才表现出来。 当行使单元测试中包含类的逻辑时,它工作得很好。
因此,可以如下重现主要设置
失败代码
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
创建此阅读器实例后,当文本包含字符实体引用时,从其中读取的任何XmlText节点都会产生截断的值。 我发现允许以高保真度读取原始值的唯一方法是完全避免XPathNavigator的使用,而是创建另一个Message
实例。 注意,由于受影响的服务正在使用MTOM编码,因此该修补程序使用了很长的路来将SOAP信封写入流中。 直接从MessageBuffer写入流会导致MIME隔离栅被写出。
修复
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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.