XmlReader
がすでに正しく配置されていることを確認するには、あなたはreader.NodeType == XmlNodeType.Element
とreader.Name == EntityElementName
かどうかを確認することができます。リーダーが正しく配置されている場合は、ReadToNextSibling()
を使用して前方にスキャンしないでください。
しかし、あなたのアルゴリズムになされるべきいくつかの改善があります。
代わりに正しいreader.Name
をチェックする、LocalName
とNamespaceURI
が予想されるかどうかをチェックし、そうでない場合、reader.ReadToNextSibling(string localName,string namespaceURI)
を呼び出します。これにより、名前空間接頭辞のハードコーディングが回避されます。これはbug to be avoidedです。
ReadOuterXml()
ではなく、reader.ReadSubtree()
と呼び出し、返されたリーダーを直接deserializer.Deserialize()
に渡します。現在のアルゴリズムはXMLを解析し、XMLを2番目のXML文字列に再フォーマットし、2番目にその文字列を解析します。 ReadSubtree()
を使用すると、XmlSerializer
は入力されたXmlReader
から直接ネストされた要素をストリーミングできるため、この余分な解析と再フォーマットは行われません。一緒にこのすべてを置く
、次の下位レベルの拡張メソッドを導入することができます
public static class XmlReaderExtensions
{
public static IEnumerable<TElement> DeserializeSequence<TElement>(this XmlReader reader, string localEntityElementName, string namespaceURI)
{
if (reader == null)
throw new ArgumentNullException();
var deserializer = new XmlSerializer(typeof(TElement));
while ((reader.NodeType == XmlNodeType.Element && reader.LocalName == localEntityElementName && reader.NamespaceURI == namespaceURI)
|| reader.ReadToNextSibling(localEntityElementName, namespaceURI))
{
// Using ReadSubtree instead of ReadOuterXml() avoids having do parse, reformat, then parse the formatted XML a second time
// by reading directly from the current stream only once.
TElement element;
using (var subReader = reader.ReadSubtree())
{
element = (TElement)deserializer.Deserialize(subReader);
}
// Consume the EndElement also (or move past the current element if reader.IsEmptyElement).
reader.Read();
yield return element;
}
}
}
をし、次のようになるためにあなたのDeserialize()
方法を変更します。
private Task<List<TAxEntity>> Deserialize(XmlReader reader)
{
var entities = reader.DeserializeSequence<TAxEntity>(EntityElementName, "" /* Pass the correct namespace here */).ToList();
return Task.FromResult(entities);
}
サンプル.Net fiddleを。インデントされたXMLを解析するときにスキップノードを含むバグが時々マスクされているので、手動XmlReader
コードは、ユニットテストさインデントおよびインデントを解除しましXMLの両方でなければならないこと
注(空白ノードがスキップ得るからである。)
出典
2017-07-21 21:49:23
dbc
スキッピングでありますReadToNextSiblingによって発生します。 ReadOuterXmlはすでにあなたのストリームを進めているので、終わりの時を知る他の方法を見つけてください。 – hoodaticus
はい、私はそれを理解しました。それが、私が読んでいないうちに楽しみにしている別の解決策を探している理由です。ありがとう! –
while(reader.Read()){...} '? – PiLHA