質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

998閲覧

C#のXDocumentにてXML形式のファイルを読み込んだ際の孫要素を無視したい

galmacher

総合スコア37

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2018/09/30 10:36

編集2018/09/30 11:22

C#で以下のXMLファイルをXDocumentで読み込み、自作クラスに格納しようとしています。

xml

1<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="300px" height="300px" viewBox="0 0 300 300" preserveAspectRatio="xMidYMid meet"> 2<g id ="ue_chu_matome"> 3 <g id ="ue_kyokusen" fill="#3a3a3a" stroke="black"> 4 <path d="M10 10 C 20 20, 40 20, 50 10Z" stroke="black" fill="transparent"/> 5 <path d="M70 10 C 70 20, 120 20, 120 10Z" stroke="black" fill="transparent"/> 6 </g> 7 8 <g id ="chu_kyokusen" fill="#3a3a3a" stroke="black"> 9 <path d="M10 60 C 20 80, 40 80, 50 60Z" stroke="black" fill="transparent"/> 10 </g> 11</g> 12 13<g id ="shita_kyokusen" fill="#3a3a3a" stroke="black"> 14 <path d="M10 110 C 20 140, 40 140, 50 110Z" stroke="black" fill="transparent"/> 15</g> 16</svg>

上記のようにgタグでグルーピングされたpathタグが存在しており、
そのpathタグはどのグループに属しているかを判別しようとしています。
ただしgタグの子にさらにgタグが居たとしても、
一番親のgタグに属しているものとして判別したいです。

現在の実装は以下の通りです。

C#

1 public class SVGDataList 2 { 3 // プロパティ用変数の定義 4 private string _gid; 5 private List<String> _PathList; 6 7 public SVGDataList(XElement value) 8 { 9 // コンストラクタでプロパティに格納 10 var pathes = value.Descendants("{http://www.w3.org/2000/svg}path"); 11 foreach (XElement path in pathes) 12 { 13 _PathList.Add(path.Attribute("d").Value); 14 } 15 _gid = value.Attribute("id").Value; 16 } 17 18 // プロパティ 19 public string Gid 20 { 21 set 22 { 23 _gid = value; 24 } 25 get 26 { 27 return _gid; 28 } 29 } 30 31 public List<String> PathList 32 { 33 get 34 { 35 return _PathList; 36 } 37 } 38 } 39 40 class Program 41 { 42 static void Main(string[] args) 43 { 44 XDocument table = XDocument.Load(@ファイルのパス"); 45 var gid = table.Descendants("{http://www.w3.org/2000/svg}g"); 46 47 foreach (XElement g in gid) 48 { 49 SVGDataList svgdata = new SVGDataList(g); 50 Console.WriteLine(svgdata.Gid + ":"); 51 foreach (string str in svgdata.PathList) 52 Console.WriteLine("\t" + str); 53 } 54 Console.ReadKey(); 55 } 56 }

結果は以下のように出力されます。
ue_chu_matome:
M10 10 C 20 20, 40 20, 50 10Z
M70 10 C 70 20, 120 20, 120 10Z
M10 60 C 20 80, 40 80, 50 60Z

ue_kyokusen:
M10 10 C 20 20, 40 20, 50 10Z
M70 10 C 70 20, 120 20, 120 10Z

chu_kyokusen:
M10 60 C 20 80, 40 80, 50 60Z

shita_kyokusen:
M10 110 C 20 140, 40 140, 50 110Z

やりたいことは、ue_kyokusenとchu_kyokusenはmatomeで取得済なので、
matome、shita_kyokusenの2要素のみをSVGDataListクラスに格納したいです。
何か良いアイデアはございませんでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

Descendants だと子孫すべてが選択されますが、Elements なら直下の子だけ選択されます。
次のコードで確かめてください。

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Xml.Linq; 5 6namespace ConsoleApp1 7{ 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 var source = @"<svg version=""1.0"" xmlns=""http://www.w3.org/2000/svg"" width=""300px"" height=""300px"" viewBox=""0 0 300 300"" preserveAspectRatio=""xMidYMid meet""> 13<g id =""ue_chu_matome""> 14 <g id =""ue_kyokusen"" fill=""#3a3a3a"" stroke=""black""> 15 <path d=""M10 10 C 20 20, 40 20, 50 10Z"" stroke=""black"" fill=""transparent""/> 16 <path d=""M70 10 C 70 20, 120 20, 120 10Z"" stroke=""black"" fill=""transparent""/> 17 </g> 18 19 <g id =""chu_kyokusen"" fill=""#3a3a3a"" stroke=""black""> 20 <path d=""M10 60 C 20 80, 40 80, 50 60Z"" stroke=""black"" fill=""transparent""/> 21 </g> 22</g> 23 24<g id =""shita_kyokusen"" fill=""#3a3a3a"" stroke=""black""> 25 <path d=""M10 110 C 20 140, 40 140, 50 110Z"" stroke=""black"" fill=""transparent""/> 26</g> 27</svg> 28"; 29 XNamespace ns = "http://www.w3.org/2000/svg"; 30 var lists = XDocument 31 .Parse(source) 32 .Element(ns + "svg") 33 .Elements(ns + "g") 34 .Select(item => new SVGDataList(item)); 35 foreach (var item in lists) 36 { 37 Console.WriteLine($"\n{item.Gid}:\n{string.Join("\n", item.PathList)}"); 38 } 39 Console.ReadKey(); 40 } 41 } 42 43 public class SVGDataList 44 { 45 // プロパティ用変数の定義 46 private string _gid; 47 private List<String> _PathList = new List<string>(); 48 49 public SVGDataList(XElement value) 50 { 51 // コンストラクタでプロパティに格納 52 var pathes = value.Descendants("{http://www.w3.org/2000/svg}path"); 53 foreach (XElement path in pathes) 54 { 55 _PathList.Add(path.Attribute("d").Value); 56 } 57 _gid = value.Attribute("id").Value; 58 } 59 60 // プロパティ 61 public string Gid 62 { 63 set 64 { 65 _gid = value; 66 } 67 get 68 { 69 return _gid; 70 } 71 } 72 73 public List<string> PathList 74 { 75 get 76 { 77 return _PathList; 78 } 79 } 80 } 81} 82```4

投稿2018/10/01 00:06

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

galmacher

2018/10/01 12:37

ありがとうございます。 想定通りの動きをしました。 今後さらに<g>タグの子が増えても問題なさそうですね。
guest

0

子のgノードの絶対パスを明確に指定すれば親のgノードは拾われません。
検証していませんが、

C#

1using System.Xml.Linq; 2using System.Xml.XPath;

を先頭に設定した上で、

C#

1 var gid = table.Descendants("{http://www.w3.org/2000/svg}g");

の行を

C#

1 IEnumerable<XElement> gid = from item 2 in table.XPathSelectElements("/svg/g/g/path") select item;

とルートパスのsvgから絶対ノード指定でpathまで指定すれば重複せずにd属性が取得できるでしょう。

投稿2018/09/30 17:56

seastar3

総合スコア2285

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

galmacher

2018/10/01 12:36

ご回答ありがとうございます。 うまく動きませんでしたが、XPathSelectElementsメソッドの存在、絶対で指定する方法もあるとのことで勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問