簡體   English   中英

如何在不使用XmlReader取消引用實體的情況下讀取XML節點的文本元素

[英]How to read the text element of an XML node without dereferencing entities using XmlReader

我試圖讀取一個XML文檔,其中包含類似下面提到的數據的元素。

通過reader.Valuereader.ReadContentAsString()reader.ReadContentAsObject()訪問文本節點會導致讀取的值被截斷為最后一個與號,因此在以下數據的情況下為ISO ^ urn:ihe:iti :XDS:2013:轉診。 使用XmlDocument可以正確讀取文本節點,因此我假設也必須有一種使用閱讀器進行此項工作的方法。

 <Slot name="urn:ihe:iti:xds:2013:referenceIdList">
              <ValueList>
                <Value>123456^^^&amp;orgID&amp;ISO^urn:ihe:iti:xds:2013:referral</Value>
                <Value>098765^^^&amp;orgID&amp;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^^^&amp;orgID&amp;ISO^urn:ihe:iti:xds:2013:referral</Value>
        <Value>098765^^^&amp;orgID&amp;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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM