場所のXMLリストをオブジェクトのセットに変換しようとしています。
XMLファイルには、場所ごとに1つのLocation要素があります。XML属性には、オブジェクトのプロパティ値が含まれています。
一部のターゲットプロパティの名前をソース属性とは異なるものにしたい。
後でオブジェクトをCSVファイルにシリアル化したいので、プロパティの順序が重要です。
これは、問題を説明するための2つの場所のサンプルです。
[xml] $InputXml = @'
<?xml version="1.0" encoding="UTF-8"?>
<CTLocations xmlns="http://www.cartrawler.com/">
<Country code="AL" name="Albania" continent="Europe">
<Location Id="7188" Name="Tirana Airport" Lat="41.42108838" Lng="19.71271276" CountryCode="AL" Address="Tirana Airport Muhamet Gjollesha Str., Muhamet Gjollesha Str., Tirana" CityName="Tirana" Airport="1" AirportCode="TIA" RailwayStation="0"/>
<Location Id="30768" Name="Tirana Downtown" Lat="41.332" Lng="19.832" CountryCode="AL" Address="Rruga E Durresit. Nr 61, Tirana" CityName="Tirana" Airport="0" RailwayStation="0"/>
</Country>
</CTLocations>
'@
私のソリューションは、属性の完全なセットを持つ要素に対して機能しますが、属性のいずれかが欠落していると失敗します。
私が使用しているセレクト-XMLの重要な要素を選択するために、コマンドレットを、そしてPSCustomObject注文し、名前を変更したプロパティを持つオブジェクトを作成します。
Select-Xml -Xml $InputXml -XPath '//ns:Location' -Namespace @{ns = 'http://www.cartrawler.com/'} |
% {
$n = $_.Node
[PSCustomObject] @{
LocationCode = $n.Id
LocationName = $n.Name
Latitude = $n.Lat
Longitude = $n.Lng
CountryCode = $n.CountryCode
FormattedAddress = $n.Address
CityName = $n.CityName
ServesAirport = $n.Airport
AirportCode = $n.AirportCode
ServesRailwayStation = $n.RailwayStation
}
}
strict-modeを設定した場合:
Set-StrictMode -Version 3.0
最初の要素にはすべての属性が含まれているため、オブジェクトに変換されます。
LocationCode : 7188
LocationName : Tirana Airport
Latitude : 41.42108838
Longitude : 19.71271276
CountryCode : AL
FormattedAddress : Tirana Airport Muhamet Gjollesha Str., Muhamet Gjollesha Str., Tirana
CityName : Tirana
ServesAirport : 1
AirportCode : TIA
ServesRailwayStation : 0
2番目の要素にはAirportCode属性がないため、PowerShellは代わりに例外を発生させます。
Property 'AirportCode' cannot be found on this object. Make sure that it exists.
At line:16 char:3
+ [PSCustomObject] @{
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
ストリクトモードをオフにすると:
Set-StrictMode -Off
PowerShellは、両方の場所をオブジェクトに変換します。欠落しているプロパティはnullです:
LocationCode : 7188
LocationName : Tirana Airport
Latitude : 41.42108838
Longitude : 19.71271276
CountryCode : AL
FormattedAddress : Tirana Airport Muhamet Gjollesha Str., Muhamet Gjollesha Str., Tirana
CityName : Tirana
ServesAirport : 1
AirportCode : TIA
ServesRailwayStation : 0
LocationCode : 30768
LocationName : Tirana Downtown
Latitude : 41.332
Longitude : 19.832
CountryCode : AL
FormattedAddress : Rruga E Durresit. Nr 61, Tirana
CityName : Tirana
ServesAirport : 0
AirportCode :
ServesRailwayStation : 0
より良い方法がある場合、これを機能させるために厳密モードをオフにしたくありません。
ストリクトモードで動作するものはすべて許容されます。T-SQLCASE式やPythonのdictgetメソッドのようなものを探していました。たぶんそれを行うXPathの方法もあります。
あなたの場合、それは簡単です:
select-Xml -Xml $InputXml -XPath '//ns:Location' -Namespace @{ns = 'http://www.cartrawler.com/'} |
% {
$n = $_.Node
[PSCustomObject] @{
LocationCode = $n.Id
LocationName = $n.Name
Latitude = $n.Lat
Longitude = $n.Lng
CountryCode = $n.CountryCode
FormattedAddress = $n.Address
CityName = $n.CityName
ServesAirport = $n.Airport
AirportCode = $(if($n.Airport -eq '1'){$n.AirportCode}else{""})
ServesRailwayStation = $n.RailwayStation
}
}
より一般的に:
select-Xml -Xml $InputXml -XPath '//ns:Location' -Namespace @{ns = 'http://www.cartrawler.com/'} |
% {
$n = $_.Node
[PSCustomObject] @{
LocationCode = $n.Id
LocationName = $n.Name
Latitude = $n.Lat
Longitude = $n.Lng
CountryCode = $n.CountryCode
FormattedAddress = $n.Address
CityName = $n.CityName
ServesAirport = $n.Airport
AirportCode = $(if($n.GetAttributeNode("AirportCode") -ne $null){$n.AirportCode}else{""})
ServesRailwayStation = $n.RailwayStation
}
}
これが書かれると、私の古いプログラマーの意見(あなたが気にしない種類)は、厳密モードを使用したい場合は、スクリプトを停止して、Java、C#、C、またはC ++の記述を開始することです。厳密モードで戦っている近似の種類は、スクリプトの+であり、これは私にとってテーブルの隅にある問題を迅速に解決するためのものです。私の意見では、厳密モードを使用すると、従来のプログラミングのすべての欠点が無関心になりますが、それは私の意見です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加