"new XmlTextReader"之间的行为不同;和"XmlReader.Create" [英] Different behaviour between "new XmlTextReader" and "XmlReader.Create"

查看:93
本文介绍了"new XmlTextReader"之间的行为不同;和"XmlReader.Create"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下源代码:

 using System;
 using System.IO;
 using System.Xml;
 using System.Xml.Schema;

 namespace TheXMLGames
 {
   class Program
   {
     static void Main(string[] args)
     {
       XmlReaderSettings settings = new XmlReaderSettings {
         Async = false,
         ConformanceLevel = ConformanceLevel.Fragment,
         DtdProcessing = DtdProcessing.Ignore,
         ValidationFlags = XmlSchemaValidationFlags.None,
         ValidationType = ValidationType.None,
         XmlResolver = null,
       };

       string head = File.ReadAllText("sample.xml");
       Stream stringStream = GenerateStreamFromString(head);

       // Variant 1
       //XmlReader reader = XmlReader.Create(stringStream);

       // Variant 2
       //XmlReader reader = XmlReader.Create(stringStream, settings);

       // Variant 3
       XmlTextReader reader = new XmlTextReader(stringStream);

       while (reader.Read())
         if (reader.NodeType != XmlNodeType.Whitespace)
           Console.WriteLine(reader.Name + ": " + reader.Value);

       // No Variant gets here without an exception,
       // but that's not the point!

       Console.ReadKey();
     }

     public static Stream GenerateStreamFromString(string s)
     {
       MemoryStream stream = new MemoryStream();
       StreamWriter writer = new StreamWriter(stream);
       writer.Write(s);
       writer.Flush();
       stream.Position = 0;
       return stream;
     }
   }
 }

sample.xml

sample.xml

 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE TestingFacility >
 <TestingFacility id="MACHINE_2015-11-11T11_11_11" version="2015-11-11">

 <Program>
   <Title>title</Title>
   <Steps>16</Steps>
 </Program>
 <Calibration>
   <Current offset="0" gain="111.11" />
   <Voltage offset="0" gain="111.11" />
 </Calibration>
 <Info type="Facilityname" value="MACHINE" />
 <Info type="Hardwareversion" value="HW11" />
 <Info type="Account" value="DJohn" />
 <Info type="Teststart" value="2015-11-11T11:11:11" />
 <Info type="Description" value="desc" />
 <Info type="Profiler" value="prof" />
 <Info type="Target" value="trgt" />

行为如下:

变体1
XmlReader.Create(stream)
System.Xml.dll中发生了类型为'System.Xml.XmlException'的未处理的异常 附加信息:出于安全原因,此XML文档中禁止使用DTD.要启用DTD处理,请将XmlReaderSettings上的DtdProcessing属性设置为Parse,然后将设置传递到XmlReader.Create方法中.

Variant 1
XmlReader.Create(stream)
An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll Additional information: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.

变体2
XmlReader.Create(流,设置)
System.Xml.dll中发生了类型为'System.Xml.XmlException'的未处理的异常 附加信息:意外的DTD声明.第2行,位置3.

Variant 2
XmlReader.Create(stream, settings)
An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll Additional information: Unexpected DTD declaration. Line 2, position 3.

变体3
新的XmlTextReader(stringStream)
System.Xml.dll中发生了类型为'System.Xml.XmlException'的未处理的异常 附加信息:发生了意外的文件结尾.以下元素未关闭:TestingFacility.第19行,位置36.

Variant 3
new XmlTextReader(stringStream)
An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll Additional information: Unexpected end of file has occurred. The following elements are not closed: TestingFacility. Line 19, position 36.

第一行之后变数1和2抛出.
变体3按照预期输出整个文件,直到结束,它都会抱怨(正确!).

Variant 1 and 2 throw after the first line.
Variant 3 outputs the whole file as expected and when it gets to the end, it complains (correctly!).

该软件的工作方式与我显然使用Variant 3一样,但是(现在)推荐的方法是通过XmlReader.Create使用Factory.

The software works as I obviously use Variant 3, but the (now) recommended way is to use the Factory via XmlReader.Create

如果我摆弄这些设置,它会变得更加奇怪.

If I fiddle with the settings, it starts getting even more weird.

如何获取最新代码并使用XmlReader.Create?

How can I get the code up-to-date and use XmlReader.Create?

完整的项目可以在这里找到: https://drive.google.com/file/d/0B55cC50M31_8T0lub25oS2QxQ00/view

The full project can be found here: https://drive.google.com/file/d/0B55cC50M31_8T0lub25oS2QxQ00/view

推荐答案

我通常不建议使用NON XML方法来解析XML文件.但是有时候,当XML无效时,其他方法是更好的选择.由于您有一个巨大的XML文件,并且您只想获取一行数据,因此下面的代码可能是最佳选择.

I don't normally recommend using a NON XML method for parsing an XML file. But sometimes when the XML is not valid other methods are a better choice. Since you have a huge XML file and you are only trying to get one line of data the code below may be the best choice.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                "<!DOCTYPE SomeDocTypeIdidntPutThere>\n" +
                "<TestingFacility id=\"MACHINE2_1970-01-01T11_22_33\" version=\"1970-01-01\">\n" +
                "<Program>\n" +
                  "<Title>Fancy Title</Title>\n" +
                  "<Steps>136</Steps>\n" +
                "</Program>\n" +
                "<Info type=\"Start\" value=\"2070-01-01T11:22:33\" />\n" +
                "<Info type=\"LotMoreOfThem\" value=\"42\" />\n";

            MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
            StreamReader reader = new StreamReader(stream);
            string inputLine = "";
            string timeStr = "";
            while ((inputLine = reader.ReadLine()) != null)
            {
                inputLine = inputLine.Trim();
                if(inputLine.StartsWith("<Info type=\"Start\""))
                {
                    string pattern = "value=\"(?'time'[^\"]+)";
                    timeStr = Regex.Match(inputLine, pattern).Groups["time"].Value;
                    break;
                }
            }
            DateTime time;
            if (timeStr.Length > 0)
            {
                time = DateTime.Parse(timeStr);
            }
        }
    }
}

​

这篇关于"new XmlTextReader"之间的行为不同;和"XmlReader.Create"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆