データ収集、パート2

データ取得に関する私の話の最初の部分では、インターネットからHTMLを取得するためにどのツールが使用されるかについて書きました。 この投稿では、このHTMLから必要なデータを取得する方法と、このデータを必要な形式に変換する方法について詳しく説明します。



HTMLの形



リソースからHTMLを取得する場合、2つのオプションがあります-すぐにXMLに変換できる(つまり、取得して使用できる)完全に形成されたHTML、または不完全な形式のHTMLのいずれかです。 残念ながら、ほとんどのHTMLは形式が不十分です。 この状況では、2つのオプションがあります。HTMLAgility Packを使用して必要なすべてのデータを引き出すか、同じライブラリを使用して結果のHTMLを「調整」し、XMLに近づけます。 閉じられていないすべてのIMG



要素を削除する方法の最も最小限の例を次に示します。



var someHtml = "<p><img src='a.gif'>hello</p>" ;<br/>

HtmlDocument doc = new HtmlDocument();<br/>

doc.LoadHtml(someHtml);<br/>

// fix images

foreach ( var node in doc.DocumentNode.SelectNodes( "//img" ))<br/>

if (!node.OuterHtml.EndsWith( "/>" ))<br/>

node.Remove();<br/>

Console.WriteLine(doc.DocumentNode.OuterHtml);<br/>

Console.ReadLine();<br/>







HTMLの修正は不要なタスクであるように思われるかもしれません-結局、同じSelectNodes()



メソッドを使用すると、この要素の形式が正しくない(不正な)場合でも、任意の要素を取得できます。 ただし、忘れてはならない利点が1つあります。正しいXMLを受け取ったら、a)このXMLのXSDを作成(または生成)できます。 およびb)XSDを受け取った後、POCOのXML構造からマッピングを生成できます。これは作業がはるかに簡単です。



マッピング



データマッピングは通常、BizTalkなどの統合システムに表示されます。 アイデアは、データセットを何かに変換することです-通常、それは実際には単に異なるデータセットです。 実際、多くの場合、これは1対1の比較ですが、異なる変換が必要になることがよくあります-たとえば、すべてのHTMLはテキストですが、数値を取得するには変換を行う必要があります( int.Parse()



など)。 これがどのように行われるかを見てみましょう。



解析時に次の(プリミティブ)構造を取得するとします。



<table><br/>

<tr><br/>

<td>Alexander</td><br/>

<td>RD</td><br/>

</tr><br/>

<tr><br/>

<td>Sergey</td><br/>

<td>MVP, RD</td><br/>

</tr><br/>

<tr><br/>

<td>Dmitri</td><br/>

<td>MVP</td><br/>

</tr><br/>

</table><br/>







ここで、このデータを次の構造にマップする必要があると想像してください。



class Person<br/>

{<br/>

public string Name { get; set; }<br/>

public bool IsMVP { get; set; }<br/>

public bool IsRD { get; set; }<br/>

}<br/>







このクラスでは、すぐにコレクションクラスを作成することをお勧めします。



public class PersonCollection : Collection<Person> {}<br/>







次に、ソースデータのXSDを生成します。 結果は次のようになります。



<xs:schema xmlns:xs= "http://www.w3.org/2001/XMLSchema" ><br/>

<xs:element name= "table" ><br/>

<xs:complexType><br/>

<xs:sequence><br/>

<xs:element name= "tr" maxOccurs= "unbounded" ><br/>

<xs:complexType><br/>

<xs:sequence><br/>

<xs:element name= "td" type= "xs:string" /><br/>

<xs:element name= "td" type= "xs:string" /><br/>

</xs:sequence><br/>

</xs:complexType><br/>

</xs:element><br/>

</xs:sequence><br/>

</xs:complexType><br/>

</xs:element><br/>

</xs:schema><br/>







それは簡単です-おそらくあまりにも簡単です。 さらに難しいのは、コレクションクラスの図を取得することです。 (Nb:スキーマの代わりに、たとえばデータベースを直接使用できますが、おそらくXSDを使用します。)警告、魔法のトリック: PersonCollection



タイプでアセンブリをコンパイルし、次のコマンドを実行します。



xsd -t:PersonCollection "04 Mapping.exe" <br/>







信じられない-このコマンドは、CLRタイプに基づいてXSDを生成します! XSD



起動は、システムの「ビットネス」でのみ意味があることに注意してください。 すべてがx86用にコンパイルされるという事実にもかかわらず、 XSD



が機能するためには、64ビットアセンブリを作成する必要がありました。 マッピングできる次のXSDファイルが判明しました。



<xs:schema elementFormDefault= "qualified" xmlns:xs= "http://www.w3.org/2001/XMLSchema" ><br/>

<xs:element name= "ArrayOfPerson" nillable= "true" type= "ArrayOfPerson" /><br/>

<xs:complexType name= "ArrayOfPerson" ><br/>

<xs:sequence><br/>

<xs:element minOccurs= "0" maxOccurs= "unbounded" name= "Person" nillable= "true" type= "Person" /><br/>

</xs:sequence><br/>

</xs:complexType><br/>

<xs:complexType name= "Person" ><br/>

<xs:sequence><br/>

<xs:element minOccurs= "1" maxOccurs= "1" name= "Name" type= "xs:string" /><br/>

<xs:element minOccurs= "1" maxOccurs= "1" name= "IsMVP" type= "xs:boolean" /><br/>

<xs:element minOccurs= "1" maxOccurs= "1" name= "IsRD" type= "xs:boolean" /><br/>

</xs:sequence><br/>

</xs:complexType><br/>

</xs:schema><br/>







さて、マッピングの左側と右側があります。 マッピング自体は、Stylus StudioやMapForceなどのアプリケーションを使用して作成できます。 マッピングは視覚的に作成されますが、作成プロセスは直感的ではないため、視覚的なマッピングを使用したことがない場合は、最初は少し苦労する必要があります。



マッピングを作成するために、 Altova MapForceプログラムを使用しました。 要するに、このプログラムは、XSD-on-XSDを含む多くの異なるマッピングを実行できます。 マッピングは、XSLT1 / 2、XQuery、Java、C#、およびC ++言語用に生成されます。 個人的には、XSLT2を目的に使用し、無料のAltovaXMLエンジンを使用して変換を開始します。 XSLTのためにMicrosoftが.Netで提供するものはすべて、本当に悲惨です。 そして、一般的な.NetのXQueryは存在しません。 いいえ、Mvp.Xmlライブラリはあまり役に立ちませんが、開発者の努力は賞品に依存しています。



最初に行うことは、使用可能なプリミティブを使用してマッピングを視覚的に記述することです。 結果は次のようになります。









次に、マッピング用のXSLTを生成します。 残っているのは、それを呼び出す方法を決定することです。 AltovaXMLを変換に使用することを考えると、コード自体は次のようになります。



public static string XsltTransform( string xml, string xslt)<br/>

{<br/>

var app = new Application();<br/>

var x = app.XSLT2;<br/>

x.InputXMLFromText = xml;<br/>

x.XSLFromText = xslt;<br/>

return x.ExecuteAndGetResultAsString();<br/>

}<br/>







XMLをコレクションに逆シリアル化するには、次のメソッドを使用します。



public static T FromXml<T>( string xml) where T : class <br/>

{<br/>

var s = new XmlSerializer( typeof (T));<br/>

using ( var sr = new StringReader(xml))<br/>

{<br/>

return s.Deserialize(sr) as T;<br/>

}<br/>

}<br/>







実際、これですべてです。XMLを受け取ったら、安全に変換できます。



string xml = File.ReadAllText( "Input.xml" );<br/>

string xslt = File.ReadAllText( "../../output/MappingProjectMapToPersonCollection.xslt" );<br/>

string result = XsltTransform(xml, xslt);<br/>

var pc2 = FromXml<PersonCollection>(result);<br/>







歌詞のマッピング



マッピングは一部の人にとっては不必要に思えるかもしれませんが、単純な場合にはこれは真実かもしれません。 しかし、追加の抽象化レベルとしてマッピングを使用すると、結果をより適切に制御し、変化する条件に適応させることができます。サイトのデザインが変化する場合、これは本当に真実です。



通常、マッピングとXMLの操作は無料ではありません。VisualStudio(2010年でも)は非常に貧弱なため、専用の有料プログラムを使用しました。 いいえ。もちろん、BizTalk(およびVS2008)でマッピングがサポートされているため、私はうそをついています。 そして当然、私たちのタスクは、ある意味で、BizTalkで「転置」できます。 そして、個人使用の場合、MSDNサブスクリプションを使用している場合は何を試すことができますか。



今日は以上です。 ソースは、いつものようにここにあります 。 コメントを歓迎します。



All Articles