VB.NET XMLWriter:ヘッダーの内容を変更する方法は?
質問
XMLファイルを作成する必要があります-パートナーはヘッダーにかなりこだわります。どうやら、ヘッダーは正確にこれである必要があります:
<?xml version="1.0"?>
しかし、XMLファイルを作成するたびに、次のような無関係なプロパティを取得します。
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
私のハッカーは、XMLWriterを使用してファイルを作成することをやめたいので、ヘッダーをより細かく制御できます。 「問題ありません。StreamWriterなどとして独自のXMLタグを作成するループを作成します。この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を削除すると、standalone = yesと表示されなくなりました。ただし、エンコーディングの追加を停止することはできません。アイデアはありますか
解決
これを行う1つの方法は、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
「ルート」も追加したことに注意してください。辞書に複数の要素が含まれる場合の要素(および辞書キーの値が&quot; root&quot;でないことを推測しています:)
他のヒント
質問が出されてから数ヶ月が経ちましたが、偶然見つけた(長年の?)解決策について言及する義務があります。 xmldeclaration全体が不要になり、必要なことは、処理命令を書くことで必要な宣言だけを書き直すだけです。
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クラスはXMLSerializableです
ヘッダーにカスタムプロパティがあると思う理由
WriteStartDocumentは、スタンドアロン属性の有無にかかわらずヘッダーを書き込みます。コードは、パートナーが受け入れないと言った属性を追加します。
&quot; utf-16&quot;の生成に使用したコードは表示しませんでしたが、StringWriterに書き込まれたと思われます。 .NETの文字列は常にUNICODEであり、文字列に書き込むと常にutf-16を取得します。ストリームに書き込むと、エンコードを制御できます。
ネクロマンシング。
独自の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
これ:
XmlWriterSettings xmlWriterSettings
= new XmlWriterSettings { OmitXmlDeclaration = true, };
次のようになります:
<?xml version="1.0"?>