XMLファイルからデータを取得するのに問題があります
-
29-09-2019 - |
質問
GoogleのジオコーディングAPIからいくつかの情報を解析しようとしていますが、XMLからデータを効率的に削除することに少し苦労しています。 たとえば、リンクを参照してください
私が本当に気にしているのは、取得することだけです short_name
から address_component
タイプがどこにあるのか administrative_area_level_1
そしてその long_name
から administrative_area_level_2
ただし、私のテストプログラムでは、私のXPathクエリは両方のクエリの結果を返しません。
public static void Main(string[] args)
{
using(WebClient webclient = new WebClient())
{
webclient.Proxy = null;
string locationXml = webclient.DownloadString("http://maps.google.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false");
using(var reader = new StringReader(locationXml))
{
var doc = new XPathDocument(reader);
var nav = doc.CreateNavigator();
Console.WriteLine(nav.SelectSingleNode("/GeocodeResponse/result/address_component[type=administrative_area_level_1]/short_name").InnerXml);
Console.WriteLine(nav.SelectSingleNode("/GeocodeResponse/result/address_component[type=administrative_area_level_2]/long_name").InnerXml);
}
}
}
誰かが私が間違っていることを見つけるのを手伝ってくれますか、それともより良い方法を勧めることができますか?
解決
あなたが探しているノードの値を引用符で入れる必要があります:
".../address_component[type='administrative_area_level_1']/short_name"
↑ ↑
他のヒント
Xpathnavigatorの代わりにLinqをXMLに使用することをお勧めします。私の経験では、XMLがそよ風を照らします。この場合、何が間違っているのか正確にはわかりません...しかし、代わりにXMLスニペットからXMLスニペットを思いつきます。
using System;
using System.Linq;
using System.Net;
using System.Xml.Linq;
class Test
{
public static void Main(string[] args)
{
using(WebClient webclient = new WebClient())
{
webclient.Proxy = null;
string locationXml = webclient.DownloadString
("http://maps.google.com/maps/api/geocode/xml?address=1600"
+ "+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false");
XElement root = XElement.Parse(locationXml);
XElement result = root.Element("result");
Console.WriteLine(result.Elements("address_component")
.Where(x => (string) x.Element("type") ==
"administrative_area_level_1")
.Select(x => x.Element("short_name").Value)
.First());
Console.WriteLine(result.Elements("address_component")
.Where(x => (string) x.Element("type") ==
"administrative_area_level_2")
.Select(x => x.Element("long_name").Value)
.First());
}
}
}
今これ は その他のコード1...しかし、私は個人的にはXpathよりも正しいことが簡単だと感じています。なぜなら、コンパイラーは私をもっと助けているからです。
編集:私がなぜ私が 一般的 明らかに長いものの、Xpathを使用するよりもこのようなコードを好む。
C#プログラム内でXPathを使用する場合、2つの異なる言語がありますが、1つだけが制御されています(C#)。 Xpathは文字列の領域に追いやられます。ビジュアルスタジオは、Xpathの表現に特別な取り扱いを与えません。そうではありません 理解する それはXpathの表現であることを意図しているので、あなたを助けることはできません。 Visual StudioがXPathについて知らないということではありません。 Dimitreが指摘するように、XSLTファイルを編集している場合、C#ファイルではなく、エラーを見つけることができます。
これは、ある言語が別の言語に埋め込まれていて、ツールが気づいていない場合はいつでも当てはまります。一般的な例は次のとおりです。
- SQL
- 正規表現
- HTML
- xpath
コードが別の言語内のデータとして提示されると、二次言語はそのツールの利点の多くを失います。
あなたの間 できる コンテキストスイッチは、Xpath(またはSQL、または正規表現など)を独自のツール(おそらく同じ実際のプログラム内で)に引き出しますが、別のファイルまたはウィンドウで)長期的にコード。コードが書かれていて、その後読まなかった場合、それは大丈夫かもしれませんが、あなたは 行う 後でコードを読むことができる必要があり、私は個人的に、これが起こると読みやすさが苦しむと信じています。
上記のLINQからXMLバージョンは、純粋なデータに文字列(要素の名前など)のみを使用し、コード(メソッド呼び出し)を使用して、「特定の名前を持つ要素を見つける」または「このフィルターを適用」などのアクションを表します。私の見解では、それはより慣用的なC#コードです。
明らかに、他の人はこの視点を共有していませんが、私がどこから来たのかを示すために拡大する価値があると思いました。
これは難しくて速くないことに注意してください ルール もちろん...場合によっては、xpath、正規表現などが最良の解決策です。この場合、私はlinqからXMLを好むでしょう、それだけです。
1 もちろん、私 たぶん......だろう それぞれを保持しています Console.WriteLine
単一の行を呼び出しますが、水平スクロールバーでコードを投稿するのは好きではありません。上記と同じインデントで正しいXPathバージョンを書くこととスクロールを回避することは、まだかなり厄介であることに注意してください。
Console.WriteLine(nav.SelectSingleNode("/GeocodeResponse/result/" +
"address_component[type='administrative_area_level_1']" +
"/short_name").InnerXml);
一般に、ビジュアルスタジオでは、スタックオーバーフローよりも長いラインがはるかにうまく機能します...
Visual StudioのXSLTファイルの一部としてXpath式を入力することをお勧めします. 。 「入力する」エラーメッセージが表示されます。これは、優れたXML/XSLT/XPathエディターです。
たとえば、私はタイピングしています:
<xsl:apply-templates select="@* | node() x"/>
すぐにエラーリストウィンドウに入ります。次のエラー:
Error 9 Expected end of the expression, found 'x'. @* | node() -->x<--
XSLTFile1.xslt 9 14 Miscellaneous Files
Xpath式がエラーを上げない場合にのみ(意図したノードも選択していることをテストする可能性があります)、この式をC#コードに入れます。.
これにより、C#プログラムを実行するときにXPath(構文とセマンティック)がないことが保証されます。
DTBの応答は正確です。以下のリンクのようなXPathテストツールを使用して、正しいXPathを見つけることができると付け加えたかった:
string url = @"http://maps.google.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false";
string value = "administrative_area_level_1";
using(WebClient client = new WebClient())
{
string wcResult = client.DownloadString(url);
XDocument xDoc = XDocument.Parse(wcResult);
var result = xDoc.Descendants("address_component")
.Where(p=>p.Descendants("type")
.Any(q=>q.Value.Contains(value))
);
}
その結果、検索している値を含む少なくとも1つの「タイプ」ノードを持つ「address_component」の列挙ができます。上記のクエリの結果は、次のデータを含むXelementです。
<address_component>
<long_name>California</long_name>
<short_name>CA</short_name>
<type>administrative_area_level_1</type>
<type>political</type>
</address_component>
XMLを使用するときにXPathを使用するよりも簡単になりがちで、メモリ内のオブジェクトの操作とクエリ、クエリ、データベースのクエリを操作するのに非常に役立つため、LINQを一般的に学習するのに少し時間を費やすことをお勧めします。参照する私のお気に入りのサイトはそうです http://www.hookedonlinq.com/