3

ストリームの途中に XML 宣言が含まれているため、整形式ではない以下の XML フラグメントを処理できるツールを作成する必要があります。

同社はすでにこれらの種類のファイルを長期間使用しているため、形式を変更するオプションはありません。

解析を行う利用可能なソース コードはありません。また、新しいツールのプラットフォームとして選択されるのは、.NET 4 以降であり、できれば C# を使用します。

フラグメントは次のようになります。

<Header>
  <Version>1</Version>
</Header>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>

XmlReaderSettings.ConformanceLevelをConformanceLevel.Fragmentに設定してXmlReaderを使用すると、完全な要素を正常に読み取ることができます。要素の開始でさえ問題ありませんが、情報を読み取っているときに、その場所で予期しない XML 宣言を読み取るため、 XmlExceptionがスローされます。<Header><Entry><Detail>XmlReader<?xml...?>

重い文字列操作以外に、これらの XML 宣言をスキップするために必要なオプションは何ですか?

フラグメントは簡単に 100 メガバイトを超えてしまうので、一度にすべてをメモリにロードするのは避けたいと思います。しかし、それが必要なことであり、私はそれに対してオープンです。

私が得る例外の例:

System.Xml.XmlException: Unexpected XML declaration.
The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it.
Line ##, position ##.
4

3 に答える 3

2

組み込みのクラスが役立つとは思いません。おそらく、余分なヘッダーを準備して削除する必要があります。サンプルが正確である場合は、次の手順を実行するだけstring.Replace(badXml, "<?xml version=\"1.0\"?>, "")で済みます。

于 2012-08-13T12:01:41.290 に答える
1

宣言が常に同じであるかどうかわからない場合は、通常のパーサーに置き換えて使用してください<?xml; )<XmlDeclaration?>/>

また、XMLの整頓されたスタイルのプログラムを介してファイルを渡してみましたか?

データを前処理して正しいXMLを出力するために使用できるSGMLライブラリもあるかもしれません。

于 2012-08-13T12:19:12.883 に答える
0

構文の強調表示が保持されるため、これを回答として追加しました。

    private void ProcessFile(string inputFileName, string outputFileName)
    {
        using (StreamReader reader = new StreamReader(inputFileName, new UTF8Encoding(false, true)))
        {
            using (StreamWriter writer = new StreamWriter(outputFileName, false, Encoding.UTF8))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    const string xmlDeclarationStart = "<?xml";
                    const string xmlDeclarationFinish = "?>";
                    if (line.Contains(xmlDeclarationStart))
                    {
                        string newLine = line.Substring(0, line.IndexOf(xmlDeclarationStart));
                        int endPosition = line.IndexOf(xmlDeclarationFinish, line.IndexOf(xmlDeclarationStart));
                        if (endPosition == -1)
                        {
                            throw new NotImplementedException(string.Format("Implementation assumption is wrong. {0} .. {1} spans multiple lines (or input file is severely misformed)", xmlDeclarationStart, xmlDeclarationFinish));
                        }
                        // the code completely strips the <?xml ... ?> part
                        // an alternative would be to make this a new XML element containing
                        // the information inside the <?xml ... ?> part as attributes
                        // just like Daren Thomas suggested
                        newLine += line.Substring(endPosition + 2);
                        line = newLine;
                    }
                    writer.WriteLine(line);
                }
            }
        }
    }
于 2013-02-13T09:10:24.260 に答える