.Netでの適切なHTMLシリアル化

すべての人に良い!



XSLTを積極的に使用してHTML(XHTMLではない)を生成する人は、有効なXML-XHTMLだけでなく、一般的には有効なHTMLを生成するためにXHTMLをサポートしないブラウザーでも生成する必要がある場合に遭遇する可能性があります同じこと。 これを行うために、XSLTで「ダーティハック」を使用しました。

この記事では、よりクリーンで美しい方法について説明しますが、残念ながら、この方法はあまり使用されません。



この方法は.Netインフラストラクチャに固有のものですが、他のプラットフォームにも同様のツールがおそらく存在します。



さて、順番に。



はじめに



XMLの情報表現は、HTMLドキュメントを記述するのに十分であり、さらに、XMLのフレームワークでは素晴らしいことは明らかです。 問題は、XMLのテキスト表現がHTMLの同じドキュメントの表現と異なる場合があることです。



問題の本質



HTMLからXMLをシリアル化する際の重要な違いは非常に簡単です。



さらに、コンテンツ自体に依存する制限があります(シリアライザーとは関係ありません)が、これらの制限を満たすことが重要です。



メソッド自体



実際、XMLをシリアル化するために、環境はXmlWriterを使用します 。これは、XMLの適切なフォーマットに関するすべての作業を処理します。 このクラスは、何らかの形でXMLを記述する必要があるほとんどすべての操作で使用されます。 特に、XSL変換( XslCompiledTransform.Transform )では、このクラスのインスタンスが宛先として使用されます。



したがって、必要なのはXmlWriterを実装することだけです。これにより、HTMLルールに従ってXMLが正しくフォーマットされます。 だから、紹介-HtmlXmlWriter



理論



HTML仕様、より具体的にはHTML5(現在はHTML5なし)を採用し、 5種類の要素が強調表示されていることわかります。



これで、HtmlXmlWriterが空の(void)要素にコンテンツを追加することを制御し、許可しないようにする必要があり、それらは常に自己終了型(<col />)になります。



純粋なテキスト(生のテキスト)にはテキストのみ(エンティティまたはコメントは不可)を含めることができますが、終了タグとして解釈できるシーケンスを含めることはできません(大文字と小文字に関係なく)。



RCDATAは子を持つことはできませんが、エンティティ参照を含むテキストのみを持つことができます。 それらのコメントも、不可能なようです。



外部(外部)要素は任意です-これはプレーンXMLです。 制限はありません。



通常の要素には必要なものを何でも含めることができますが、必要なのは終了タグだけです。



実装



まあ、実際には、ここでは実装を行いません。複雑ではなく、誰でも自分で実装できます。 私は自分でそれをしました。そして、おそらくそれを文書化するときに、彼らが涙を流して私に懇願するならば、私はそれをある種のコードリポジトリに投稿します。 ここでは、有用なメモのみを提供します(少し面倒です)。



HtmlXmlWriterはXmlWriterの子孫になります。 XmlWriterのサードパーティインスタンス(コンストラクターに渡す必要があります)を集約し、デフォルトで適切なメソッドを呼び出します。



HtmlXmlWriterは、現在の要素(最後の要素の名前と型)を追跡し、これをXmlWriter.WriteStartElement / WriteEndElementメソッドで定義する必要があります 。 また、属性(WriteStartAttribute / WriteEndAttribute)上にあるかどうかも追跡する必要があります。



要素(WriteEndElement / WriteFullEndElement)を閉じるときは、要素のタイプに応じてWriteEndElementまたはWriteFullEndElementを選択します。



XmlWriterは一部の文字をエスケープするため、最も難しい部分は生のテキスト要素です。 したがって、テキスト出力(WriteCharEntity、WriteString、WriteSurrogateCharEntity)をWriteRawで置き換える必要があります。 ただし、ここでは、テキストに終了タグがないように制御することを忘れてはなりません。



おわりに



そのようなクラスができたら、それをXSL変換(または他の場所)に簡単に渡すことができ、XHTMLから通常のHTMLを取得できるので、どんな愚かなHTMLパーサーでもこれを理解できます。



All Articles