VB.NET XMLWriter:如何更改标头中的内容?

发布于 2024-07-24 23:46:18 字数 1275 浏览 3 评论 0原文

我需要制作一个 XML 文件 - 而合作伙伴对标头相当挑剔。 显然,标头必须是这样的:

<?xml version="1.0"?>

但是每当我创建一个 XML 文件时,我都会得到这样的无关属性:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

我内心的黑客想要停止使用 XMLWriter 来创建文件,以便我对标头有更多的控制; “没问题,我只需编写一个循环,将其自己的 XML 标记作为 StreamWriter 或其他东西,忘记这个 XMLWriter 对象......”但我必须承认 XMLWriter 到目前为止使用起来相当优雅; 当然,我可以在某些地方更改 XMLWriterSettings 对象来表示“请停止将自定义属性放入 XML 标头”,对吗?

以下是相关的 VB 代码:

    Dim settings As New XmlWriterSettings()
    settings.Indent = True
    settings.IndentChars = "    "
    settings.NewLineChars = "\n"
    Using writer As XmlWriter = XmlWriter.Create(strFileName, settings)
            writer.WriteStartDocument(True)
            For Each kvp As KeyValuePair(Of String, String) In dictArguments

                 Dim key As String = kvp.Key
                 Dim value As String = kvp.Value

                 writer.WriteStartElement(key)
                 writer.WriteString(value)
                 writer.WriteEndElement()

            Next

    End Using

完美运行; 但我找不到控制标题的方法。 当然,我可以找到一种方法将其完全删除,但这不是我们想要做的。

编辑:感谢您的帮助; 到目前为止,一旦我们删除了 WriteStartDocument,它现在就不再显示独立=是。 但是我无法让它停止添加编码。 有什么想法吗?

I have a requirement to make an XML file - and the partner is rather sticky about the header. Apparently, the header must be exactly this:

<?xml version="1.0"?>

But whenever I create an XML file I get extraneous properties like this:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

The hacker in me wants to stop using XMLWriter to make the file so that I have more control over the header; "no problem, I'll just write a loop that makes its own XML tags as a StreamWriter or something, forget this XMLWriter object..." but I must admit that XMLWriter has been rather elegant to use so far; surely there must be something where I can change the XMLWriterSettings object to say "stop putting your custom properties in to the XML header please", right?

Here's the relevant VB code:

    Dim settings As New XmlWriterSettings()
    settings.Indent = True
    settings.IndentChars = "    "
    settings.NewLineChars = "\n"
    Using writer As XmlWriter = XmlWriter.Create(strFileName, settings)
            writer.WriteStartDocument(True)
            For Each kvp As KeyValuePair(Of String, String) In dictArguments

                 Dim key As String = kvp.Key
                 Dim value As String = kvp.Value

                 writer.WriteStartElement(key)
                 writer.WriteString(value)
                 writer.WriteEndElement()

            Next

    End Using

Works perfectly; but I can't find a way to control the header. I can find a way to remove it entirely of course but that's not what we want to do.

Edit: thanks for the help; so far once we removed the WriteStartDocument it now no longer displays standalone = yes. I can't get it to stop adding the encoding however. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

叹倦 2024-07-31 23:46:19

我知道自提出问题以来已经过去了几个月,但是我觉得有必要提及我偶然发现的一个(长期存在的?)解决方案。 它确实消除了整个 xml 声明,您所需要做的就是通过编写处理指令来重写您需要的声明。

XmlFragmentWriter - 省略 Xml 声明以及 XSD 和 XSI 命名空间

这是 VB 中的类

Imports System.Xml
Imports System.IO
Imports System.Text

Class XmlFragmentWriter
Inherits XmlTextWriter

Public Sub New(ByVal w As TextWriter)
    MyBase.New(w)
End Sub

Public Sub New(ByVal w As Stream, ByVal encoding As Encoding)
    MyBase.New(w, encoding)
End Sub

Public Sub New(ByVal filename As String, ByVal encoding As Encoding)
    MyBase.New(New FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None), encoding)
End Sub


Private _skip As Boolean = False

Public Overrides Sub WriteStartAttribute(ByVal prefix As String, ByVal localName As String, ByVal ns As String)
    ' STEP 1 - Omits XSD and XSI declarations. 
    ' From Kzu - http://weblogs.asp.net/cazzu/archive/2004/01/23/62141.aspx
    If prefix = "xmlns" AndAlso (localName = "xsd" OrElse localName = "xsi") Then
        _skip = True
        Return
    End If
    MyBase.WriteStartAttribute(prefix, localName, ns)

End Sub

Public Overrides Sub WriteString(ByVal text As String)
    If _skip Then
        Return
    End If
    MyBase.WriteString(text)

End Sub

Public Overrides Sub WriteEndAttribute()
    If _skip Then
        ' Reset the flag, so we keep writing.
        _skip = False
        Return
    End If
    MyBase.WriteEndAttribute()

End Sub

Public Overrides Sub WriteStartDocument()
    ' STEP 2: Do nothing so we omit the xml declaration.
End Sub
End Class

以及这里的用法:

 Dim f As New XmlSerializer(GetType(OFXg)) 
        Dim w As New XmlFragmentWriter("c:\books1.xml", Nothing) 
        w.Formatting = Formatting.Indented 
        w.WriteProcessingInstruction("xml", "version=""1.0""") 
        f.Serialize(w, RTofx) 
        w.Close() 
  

当然,OFXg 类是 XMLSerialized

I know its been a few months since the question was asked, however I feel obliged to mention a (long-standing?) solution that I stumbled accross. It does do away with the entire xmldeclaration, and all you need to dois re-write just the declaration you need by writting a proccesing instruction.

XmlFragmentWriter - Omiting the Xml Declaration and the XSD and XSI namespaces

And here is the class in VB

Imports System.Xml
Imports System.IO
Imports System.Text

Class XmlFragmentWriter
Inherits XmlTextWriter

Public Sub New(ByVal w As TextWriter)
    MyBase.New(w)
End Sub

Public Sub New(ByVal w As Stream, ByVal encoding As Encoding)
    MyBase.New(w, encoding)
End Sub

Public Sub New(ByVal filename As String, ByVal encoding As Encoding)
    MyBase.New(New FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None), encoding)
End Sub


Private _skip As Boolean = False

Public Overrides Sub WriteStartAttribute(ByVal prefix As String, ByVal localName As String, ByVal ns As String)
    ' STEP 1 - Omits XSD and XSI declarations. 
    ' From Kzu - http://weblogs.asp.net/cazzu/archive/2004/01/23/62141.aspx
    If prefix = "xmlns" AndAlso (localName = "xsd" OrElse localName = "xsi") Then
        _skip = True
        Return
    End If
    MyBase.WriteStartAttribute(prefix, localName, ns)

End Sub

Public Overrides Sub WriteString(ByVal text As String)
    If _skip Then
        Return
    End If
    MyBase.WriteString(text)

End Sub

Public Overrides Sub WriteEndAttribute()
    If _skip Then
        ' Reset the flag, so we keep writing.
        _skip = False
        Return
    End If
    MyBase.WriteEndAttribute()

End Sub

Public Overrides Sub WriteStartDocument()
    ' STEP 2: Do nothing so we omit the xml declaration.
End Sub
End Class

and the usage here:

    Dim f As New XmlSerializer(GetType(OFXg))
      Dim w As New XmlFragmentWriter("c:\books1.xml", Nothing)
      w.Formatting = Formatting.Indented
      w.WriteProcessingInstruction("xml", "version=""1.0""")
      f.Serialize(w, RTofx)
      w.Close()

Of Course the OFXg class is an XMLSerializable

沦落红尘 2024-07-31 23:46:19

为什么您认为标头中有自定义属性?

WriteStartDocument 写入带有或不带有独立属性的标头。 您的代码添加了您所说的合作伙伴不接受的属性。

您没有显示用于生成“utf-16”的代码,但我怀疑它写入了 StringWriter。 .NET 中的字符串始终是 UNICODE,并且在写入字符串时始终会得到 utf-16。 如果写入流,您就可以控制编码。

Why do you believe there are custom properties in the header?

WriteStartDocument writes the header with or without the standalone attribute. Your code adds the attribute you said your partner does not accept.

You did not show the code that used to produce the "utf-16", but I suspect it wrote to a StringWriter. Strings in .NET are always UNICODE, and you'll always get utf-16 when you write to a string. If you write to a stream, you get to control the encoding.

千里故人稀 2024-07-31 23:46:19

死灵术。

您可以创建自己的 XmlTextWriter 并覆盖 WriteStartDocument。

示例:

public class XmlTextWriterIndentedStandaloneNo : System.Xml.XmlTextWriter
{

    public bool bStandAlone = false;
    public bool bWriteStartDocument = true;
    public bool bOmitEncodingAndStandAlone = true;


    public XmlTextWriterIndentedStandaloneNo(System.IO.TextWriter w)
        : base(w)
    {
        Formatting = System.Xml.Formatting.Indented;
    } // End Constructor 


    public XmlTextWriterIndentedStandaloneNo(string strFileName, System.Text.Encoding teEncoding)
        : base(strFileName, teEncoding)
    {
        Formatting = System.Xml.Formatting.Indented;
    } // End Constructor 


    public XmlTextWriterIndentedStandaloneNo(System.IO.Stream w, System.Text.Encoding teEncoding)
        : base(w, teEncoding)
    {
        Formatting = System.Xml.Formatting.Indented;
    } // End Constructor 


    public override void WriteStartDocument(bool standalone)
    {
        if (bWriteStartDocument)
        {
            if (bOmitEncodingAndStandAlone)
            {
                this.WriteProcessingInstruction("xml", "version='1.0'");
                return;
            } // End if (bOmitEncodingAndStandAlone) 

            base.WriteStartDocument(bStandAlone);
        }

    } // End Sub WriteStartDocument 


    public override void WriteStartDocument()
    {
        // Suppress by ommitting WriteStartDocument
        if (bWriteStartDocument)
        {

            if (bOmitEncodingAndStandAlone)
            {
                this.WriteProcessingInstruction("xml", "version='1.0'");
                return;
            } // End if (bOmitEncodingAndStandAlone)

            base.WriteStartDocument(bStandAlone);
            // False: Standalone="no"
        } // End if (bWriteStartDocument)

    } // End Sub WriteStartDocument 


} // End Class XmlTextWriterIndentedStandaloneNo 

VB.NET

Public Class XmlTextWriterIndentedStandaloneNo
    Inherits System.Xml.XmlTextWriter

    Public bStandAlone As Boolean = False
    Public bWriteStartDocument As Boolean = True
    Public bOmitEncodingAndStandAlone As Boolean = True


    Public Sub New(w As System.IO.TextWriter)
        MyBase.New(w)
        Formatting = System.Xml.Formatting.Indented
    End Sub
    ' End Constructor 

    Public Sub New(strFileName As String, teEncoding As System.Text.Encoding)
        MyBase.New(strFileName, teEncoding)
        Formatting = System.Xml.Formatting.Indented
    End Sub
    ' End Constructor 

    Public Sub New(w As System.IO.Stream, teEncoding As System.Text.Encoding)
        MyBase.New(w, teEncoding)
        Formatting = System.Xml.Formatting.Indented
    End Sub
    ' End Constructor 

    Public Overrides Sub WriteStartDocument(standalone As Boolean)
        If bOmitEncodingAndStandAlone Then
            Me.WriteProcessingInstruction("xml", "version='1.0'")
            Return
        End If
        ' End if (bOmitEncodingAndStandAlone) 
        If bWriteStartDocument Then
            MyBase.WriteStartDocument(bStandAlone)
        End If
    End Sub
    ' End Sub WriteStartDocument 

    Public Overrides Sub WriteStartDocument()
        If bOmitEncodingAndStandAlone Then
            Me.WriteProcessingInstruction("xml", "version='1.0'")
            Return
        End If
        ' End if (bOmitEncodingAndStandAlone)
        ' Suppress by ommitting WriteStartDocument
        If bWriteStartDocument Then
                ' False: Standalone="no"
            MyBase.WriteStartDocument(bStandAlone)
        End If
        ' End if (bWriteStartDocument)
    End Sub
    ' End Sub WriteStartDocument 

End Class
' End Class XmlTextWriterIndentedStandaloneNo 

使用示例:

//using (System.Xml.XmlTextWriter wr = new System.Xml.XmlTextWriter(System.IO.Path.Combine(strBasePath, "TestFile.xml"), System.Text.Encoding.UTF8))
//using (System.Xml.XmlWriter wr = System.Xml.XmlWriter.Create(System.IO.Path.Combine(strBasePath, "TestFile.xml"), xwsSettings))
using (System.Xml.XmlWriter wr = new XmlTextWriterIndentedStandaloneNo(System.IO.Path.Combine(strBasePath, "TestFile.xml"), System.Text.Encoding.UTF8))
{
    //wr.Formatting = System.Xml.Formatting.None; // here's the trick !

    xdoc.Save(wr);
    wr.Flush();
    wr.Close();
} // End Using wr

Necromancing.

You can create your own XmlTextWriter and override WriteStartDocument.

Example:

public class XmlTextWriterIndentedStandaloneNo : System.Xml.XmlTextWriter
{

    public bool bStandAlone = false;
    public bool bWriteStartDocument = true;
    public bool bOmitEncodingAndStandAlone = true;


    public XmlTextWriterIndentedStandaloneNo(System.IO.TextWriter w)
        : base(w)
    {
        Formatting = System.Xml.Formatting.Indented;
    } // End Constructor 


    public XmlTextWriterIndentedStandaloneNo(string strFileName, System.Text.Encoding teEncoding)
        : base(strFileName, teEncoding)
    {
        Formatting = System.Xml.Formatting.Indented;
    } // End Constructor 


    public XmlTextWriterIndentedStandaloneNo(System.IO.Stream w, System.Text.Encoding teEncoding)
        : base(w, teEncoding)
    {
        Formatting = System.Xml.Formatting.Indented;
    } // End Constructor 


    public override void WriteStartDocument(bool standalone)
    {
        if (bWriteStartDocument)
        {
            if (bOmitEncodingAndStandAlone)
            {
                this.WriteProcessingInstruction("xml", "version='1.0'");
                return;
            } // End if (bOmitEncodingAndStandAlone) 

            base.WriteStartDocument(bStandAlone);
        }

    } // End Sub WriteStartDocument 


    public override void WriteStartDocument()
    {
        // Suppress by ommitting WriteStartDocument
        if (bWriteStartDocument)
        {

            if (bOmitEncodingAndStandAlone)
            {
                this.WriteProcessingInstruction("xml", "version='1.0'");
                return;
            } // End if (bOmitEncodingAndStandAlone)

            base.WriteStartDocument(bStandAlone);
            // False: Standalone="no"
        } // End if (bWriteStartDocument)

    } // End Sub WriteStartDocument 


} // End Class XmlTextWriterIndentedStandaloneNo 

VB.NET

Public Class XmlTextWriterIndentedStandaloneNo
    Inherits System.Xml.XmlTextWriter

    Public bStandAlone As Boolean = False
    Public bWriteStartDocument As Boolean = True
    Public bOmitEncodingAndStandAlone As Boolean = True


    Public Sub New(w As System.IO.TextWriter)
        MyBase.New(w)
        Formatting = System.Xml.Formatting.Indented
    End Sub
    ' End Constructor 

    Public Sub New(strFileName As String, teEncoding As System.Text.Encoding)
        MyBase.New(strFileName, teEncoding)
        Formatting = System.Xml.Formatting.Indented
    End Sub
    ' End Constructor 

    Public Sub New(w As System.IO.Stream, teEncoding As System.Text.Encoding)
        MyBase.New(w, teEncoding)
        Formatting = System.Xml.Formatting.Indented
    End Sub
    ' End Constructor 

    Public Overrides Sub WriteStartDocument(standalone As Boolean)
        If bOmitEncodingAndStandAlone Then
            Me.WriteProcessingInstruction("xml", "version='1.0'")
            Return
        End If
        ' End if (bOmitEncodingAndStandAlone) 
        If bWriteStartDocument Then
            MyBase.WriteStartDocument(bStandAlone)
        End If
    End Sub
    ' End Sub WriteStartDocument 

    Public Overrides Sub WriteStartDocument()
        If bOmitEncodingAndStandAlone Then
            Me.WriteProcessingInstruction("xml", "version='1.0'")
            Return
        End If
        ' End if (bOmitEncodingAndStandAlone)
        ' Suppress by ommitting WriteStartDocument
        If bWriteStartDocument Then
                ' False: Standalone="no"
            MyBase.WriteStartDocument(bStandAlone)
        End If
        ' End if (bWriteStartDocument)
    End Sub
    ' End Sub WriteStartDocument 

End Class
' End Class XmlTextWriterIndentedStandaloneNo 

Usage example:

//using (System.Xml.XmlTextWriter wr = new System.Xml.XmlTextWriter(System.IO.Path.Combine(strBasePath, "TestFile.xml"), System.Text.Encoding.UTF8))
//using (System.Xml.XmlWriter wr = System.Xml.XmlWriter.Create(System.IO.Path.Combine(strBasePath, "TestFile.xml"), xwsSettings))
using (System.Xml.XmlWriter wr = new XmlTextWriterIndentedStandaloneNo(System.IO.Path.Combine(strBasePath, "TestFile.xml"), System.Text.Encoding.UTF8))
{
    //wr.Formatting = System.Xml.Formatting.None; // here's the trick !

    xdoc.Save(wr);
    wr.Flush();
    wr.Close();
} // End Using wr
一梦浮鱼 2024-07-31 23:46:19

这:

XmlWriterSettings xmlWriterSettings 
    = new XmlWriterSettings { OmitXmlDeclaration = true, };

会给你这个:

<?xml version="1.0"?>

This:

XmlWriterSettings xmlWriterSettings 
    = new XmlWriterSettings { OmitXmlDeclaration = true, };

will give you this:

<?xml version="1.0"?>
油饼 2024-07-31 23:46:18

执行此操作的一种方法是使用 WriteProcessingInstruction 方法自己控制初始处理指令,因此:

    Dim settings As New XmlWriterSettings()
    settings.Indent = True
    settings.IndentChars = "    "
    Using writer As XmlWriter = XmlWriter.Create(strFileName, settings)
        writer.WriteProcessingInstruction("xml", "version='1.0'")
        writer.WriteStartElement("root")
        For Each kvp As KeyValuePair(Of String, String) In dictArguments

            Dim key As String = kvp.Key
            Dim value As String = kvp.Value

            writer.WriteStartElement(key)
            writer.WriteString(value)
            writer.WriteEndElement()

        Next
        writer.WriteEndElement()

    End Using

请注意,我还添加了一个“根”元素,以防您的字典包含多个元素(我猜没有一个元素)字典键值的一个是“root”:)

One way of doing this is to take control of the initial processing instruction yourself with the WriteProcessingInstruction method thus:

    Dim settings As New XmlWriterSettings()
    settings.Indent = True
    settings.IndentChars = "    "
    Using writer As XmlWriter = XmlWriter.Create(strFileName, settings)
        writer.WriteProcessingInstruction("xml", "version='1.0'")
        writer.WriteStartElement("root")
        For Each kvp As KeyValuePair(Of String, String) In dictArguments

            Dim key As String = kvp.Key
            Dim value As String = kvp.Value

            writer.WriteStartElement(key)
            writer.WriteString(value)
            writer.WriteEndElement()

        Next
        writer.WriteEndElement()

    End Using

Note that I've also added a "root" element in case your dictionary contains more than one element (and I'm guessing that none of the dictionary key values is "root" :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文