2017-02-08 12 views
0

XmlReader.Read()XmlReader.ReadStartElement()の「不一致」を理解しようとしています。以下のreader1では、すべてが期待されます。つまり、xml全体を読むには3つの読みが必要です。さらに重要なことは、第1回目の読書時、すなわち<firstname>を読むとき、reader1.Valueは空である。そして第2の読書reader1.Valueはテキストノードの値です。XmlReader.Read()とXmlReader.ReadStartElement()の間の不一致

しかし、私の知る限りではReadStartElement()は内部Read()を呼び出し、それが唯一のXmlNodeType例えばを読む必要があるためreader2に、私は同じ読み順を期待していますここでは<firstname>です。 ReadStartElement("firstname")の代わりに、それが名前firstnameの開始要素であるかどうかと、Read()を呼び出しているかどうかを確認することができます。 ReadStartElement("firstname")の直後にreader2.Valueが空でないのはなぜですか? 私はこれを最初に@lesscodeの質問で尋ねました。彼の説明は、msdnによれば、ReadStartElement()XmlReaderを次のノードに進め、reader.Valueは現在のノードの値です。もしそうならば、Read()ReadStartElement()の間でこれは矛盾していませんか?Read()を使用すると、後で値を取得しなければならないので、ReadStartElement()を使用すると、あらかじめValueを取得する必要があります。

var simpleElement = "<firstname>Jim</firstname>"; 
using (var reader1 = XmlReader.Create(new StringReader(simpleElement))) 
{ 
    var i = 1; 
    while (reader1.Read()) 
    { 
     WriteLine($"i = {i++}; value = {reader1.Value}"); 
    }   
} 

using (var reader2 = XmlReader.Create(new StringReader(simpleElement))) 
{ 
// this internally calls Read() which should have ONLY read the 'firstname' start element node. 
    reader2.ReadStartElement("firstname"); 

// prints Jim; but why??? The text node has NOT been read yet! 
    WriteLine(reader2.Value); 

    reader2.Read(); //WHY needs this line given text node has been read already? 
    reader2.ReadEndElement(); 

} 
+0

繰り返しタグを含むxmlのサンプルを投稿します。 – jdweng

+0

@jdweng xmlのサンプルはありません。 ジムはXML全体です。私は 'XmlReader()'がどのように動作するかをテストしており、この '問題'を見いだしています。 – stt106

+0

@JonSkeetどんなアイデアですか? – stt106

答えて

1

あなたはGithubの上のソースコードを確認することができます:XmlReader.cs

あなたは下記見ることができるように、方法は同じ動作を持っていない:

// Checks that the current node is an element and advances the reader to the next node. 
public virtual void ReadStartElement() { 
    if (MoveToContent() != XmlNodeType.Element) { 
     throw new XmlException(Res.Xml_InvalidNodeType, this.NodeType.ToString(), this as IXmlLineInfo); 
    } 
    Read(); 
} 

// Checks whether the current node is a content (non-whitespace text, CDATA, Element, EndElement, EntityReference 
// or EndEntity) node. If the node is not a content node, then the method skips ahead to the next content node or 
// end of file. Skips over nodes of type ProcessingInstruction, DocumentType, Comment, Whitespace and SignificantWhitespace. 
public virtual XmlNodeType MoveToContent() { 
    do { 
     switch (this.NodeType) { 
      case XmlNodeType.Attribute: 
       MoveToElement(); 
       goto case XmlNodeType.Element; 
      case XmlNodeType.Element: 
      case XmlNodeType.EndElement: 
      case XmlNodeType.CDATA: 
      case XmlNodeType.Text: 
      case XmlNodeType.EntityReference: 
      case XmlNodeType.EndEntity: 
       return this.NodeType; 
     } 
    } while (Read()); 
    return this.NodeType; 
} 

のでReadStartElement方法は、MoveToContentウィッヒは、コンテンツノードを見つけるためにいくつかのRead電話をかけることができます呼び出します。この後、ReadStartElementは、現在の開始要素を読み取ります。

+0

うわー、それは完全に理にかなっています。 sample xml 'ReadStartElement()'は 'Read()'を2回呼び出します。 'MoveToContent()'に1回、 'MoveToContent()'の後に1回です。 Githubのソースコードを見てくれてありがとうと嬉しく思います! – stt106

+0

あなたは大歓迎です。 –

+0

こんにちは、これについて別の質問があります。 'reader2.ReadStartElement(" firstname ")'は 'Read()'を2回呼び出すので、テキストノードは 'reader2.ReadStartElement(" firstname ")'の後にすでに読み込まれていることに同意します。しかし、なぜ 'reader2.ReadEndElement()'を呼び出す前に 'reader2.Read()'をもう一度呼び出す必要がありますか?私はこれを反映するために質問を更新しました。 – stt106

関連する問題