简体   繁体   English

将 XmlTextWriter object 解析为字符串

[英]Parsing XmlTextWriter object to String

I'm building a class library in C# which uses the XmlTextWriter class to build an XML which is then exported as a HTML document. I'm building a class library in C# which uses the XmlTextWriter class to build an XML which is then exported as a HTML document.

However when I save the file with a.html extension using the XmlTextWriter object as content, the resulting file only contains the text "System.Xml.XmlTextWriter"但是,当我使用 XmlTextWriter object 作为内容保存扩展名为 .html 的文件时,生成的文件仅包含文本“System.Xml.XmlTextWriter”

This comes up in the method defined below, specifically in the final line:-这出现在下面定义的方法中,特别是在最后一行:-

public void SaveAsHTML(string filepath)
        {
            XmlTextWriter html;
            html = new XmlTextWriter(@"D:/HTMLWriter/XML/HTMLSaveAsConfig.xml", System.Text.Encoding.UTF8);
            html.WriteStartDocument();
            html.WriteStartElement("html");
            html.WriteRaw(Convert.ToString(Head));
            html.WriteRaw(Convert.ToString(Body));
            html.WriteEndElement();
            html.WriteEndDocument();
            html.Flush();
            html.Close();
            System.IO.File.WriteAllText(filepath, html.ToString());
        }

For context, the variables Head and Body are also XmlTextWriter objects containing what will become the and elements of the html file respectively.对于上下文,变量 Head 和 Body 也是 XmlTextWriter 对象,分别包含将成为 html 文件的元素的内容。

I've tried using Convert.ToString(), which causes the same issue.我试过使用 Convert.ToString(),这会导致同样的问题。

I'm tempted to try overriding the ToString() method for my class as a fix, potentially using the XmlSerializer class.我很想尝试覆盖我的 class 的 ToString() 方法作为修复,可能使用 XmlSerializer class。 However I was wondering if there's a less noisy way of returning the Xml object as a string?但是我想知道是否有一种噪音较小的方式将 Xml object 作为字符串返回?

The following function will extract the string from the System.Xml.XmlTextWriter objects you've created as Head and Body .以下 function 将从您创建为HeadBodySystem.Xml.XmlTextWriter对象中提取字符串。

private string XmlTextWriterToString(XmlTextWriter writer)
{
    // Ensure underlying stream is flushed.
    writer.Flush();
    // Reset position to beginning of stream.
    writer.BaseStream.Position = 0;
    using (var reader = new StreamReader(writer.BaseStream))
    {
        // Read and return content of stream as a single string
        var result = reader.ReadToEnd();
        return result;
    }
}

Some caveats here are that the underlying System.IO.Stream object associated with the System.Xml.XmlTextWriter must support both 'read' and 'seek' operations (ie, both Stream.CanRead and System.CanSeek properties must return true , respectively). Some caveats here are that the underlying System.IO.Stream object associated with the System.Xml.XmlTextWriter must support both 'read' and 'seek' operations (ie, both Stream.CanRead and System.CanSeek properties must return true , respectively) .

I've made the following edits to your original code:我对您的原始代码进行了以下编辑:

  1. Replaced the Convert.ToString () calls with calls to this new function.Convert.ToString ()调用替换为对这个新 function 的调用。
  2. Made an assumption that you're intending to write to the file specified by the filepath parameter to your SaveAsHTML () function, and not the hard-coded path.假设您打算将文件filepath参数指定的文件写入您的SaveAsHTML () function,而不是硬编码路径。
  3. Wrapped the creation (and use, and disposal) of the System.Xml.XmlTextWriter in a using block (if you're not familiar, see What are the uses of “using” in C#? ).System.Xml.XmlTextWriter的创建(以及使用和处置)包装在using块中(如果您不熟悉,请参阅C# 中“使用”的用途是什么? )。

Following is your code with those changes.以下是您进行这些更改的代码。

public void SaveAsHTML(string filepath)
{
    using (var html = new XmlTextWriter(filepath, System.Text.Encoding.UTF8))
    {
        html.WriteStartDocument();
        html.WriteStartElement("html");
        html.WriteRaw(XmlTextWriterToString(Head));
        html.WriteRaw(XmlTextWriterToString(Body));
        html.WriteEndElement();
        html.WriteEndDocument();
        html.Flush();
        html.Close();
    }
}

Another thing of which to be mindful is that, not knowing for sure from the code provided how they're being managed, the lifetimes of Head and Body are subject to the same exception-based resource leak potential that html was before wrapping it in the using block.需要注意的另一件事是,从提供的代码中无法确定如何管理它们, HeadBody的生命周期受到与html在将其包装在using块。

A final thought: the page for System.Xml.XmlTextWriter notes the following: Starting with the .NET Framework 2.0, we recommend that you create XmlWriter instances by using the XmlWriter.Create method and the XmlWriterSettings class to take advantage of new functionality.最后的想法: System.Xml.XmlTextWriter的页面注释如下:从 .NET Framework 2.0 开始,我们建议您使用 XmlWriter.Create 方法和 XmlWriterSettings ZA2F2ED4F8EBC2CBB4ZC21 的新功能创建 XmlWriter 实例

The last line writes the value of XmlTextWriter.ToString(), which does not return the text representation of the XML you wrote.最后一行写入 XmlTextWriter.ToString() 的值,它不会返回您编写的 XML 的文本表示形式。 Try leaving off the last line, it looks like your XmlTextWriter is already writing to a file.尝试离开最后一行,看起来您的 XmlTextWriter 已经在写入文件。

@PhilBrubaker's solution seems to be on the right track. @PhilBrubaker 的解决方案似乎在正确的轨道上。 There are still a few bugs in my code that I'm working towards getting a fix for, but the good news is that the casting seems to be working now.我的代码中仍然存在一些错误,我正在努力修复,但好消息是铸造现在似乎正在工作。

protected string XmlToString(XmlWriter xmlBody)
        {
            XmlTextWriter textXmlBody = (XmlTextWriter)xmlBody;
            textxmlBody.BaseStream.Position = 0;
            using (var reader = new StreamReader(textXmlBody.BaseStream))
            {
                var result = reader.ReadToEnd();
                reader.Dispose();
                return result;
            }
        }

I've changed the input parameter type from XmlWriter and cast it explicitly to XmlTextWriter in the method, this is so that the method also works when the Create() method is used instead of an initialisation as recommended for .NET 2.0.我已将输入参数类型从 XmlWriter 更改并在方法中将其显式转换为 XmlTextWriter,这样当使用 Create() 方法而不是 .NET 2.0 推荐的初始化时,该方法也可以工作。 It's not 100% reliable at the moment as XmlWriter doesn't always cast correctly to XmlTextWriter (depending on the features), but that's out of the scope for this thread and I'm investigating that separately.目前它不是 100% 可靠的,因为 XmlWriter 并不总是正确地转换为 XmlTextWriter(取决于功能),但这不在此线程的 scope 范围内,我正在单独调查。

Thanks for your help!谢谢你的帮助!

On a side note, the using block is something I haven't come across before, but it's provided so many solutions across the board for me.附带说明一下, using 块是我以前没有遇到过的,但它为我提供了很多全面的解决方案。 So thanks for that too!所以也谢谢你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM