문제
저는 LINQ에서 XML 초보자이며 KML 초보자입니다. 그러니 나와 함께.
내 목표는 KML 파일에서 개별 플레이스 마크를 추출하는 것입니다. 내 KML이 시작됩니다.
<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="http://earth.google.com/kml/2.0">
<name>Concessions</name>
<visibility>1</visibility>
<Folder>
<visibility>1</visibility>
<Placemark>
<name>IN920211</name>
<Style>
<PolyStyle>
<color>80000000</color>
</PolyStyle>
</Style>
<Polygon>
<altitudeMode>relativeToGround</altitudeMode>
<outerBoundaryIs>
<LinearRing>
<coordinates>11.728374,1.976421,0 11.732967,1.965322,0 11.737225,1.953161,0 11.635858,1.940812,0 11.658102,1.976874,0 11.728374,1.976421,0 </coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
<Placemark>
...
이것은 내가 얻은 한 다음과 같습니다.
Dim Kml As XDocument = XDocument.Load(Server.MapPath("../kmlimport/ga.kml"))
Dim Placemarks = From Placemark In Kml.Descendants("Placemark") _
Select Name = Placemark.Element("Name").Value
지금까지 좋은 - KML.Descendants ( "Placemark")는 빈 열거를 제공합니다. kml.descendants에는 모든 노드가 포함되어 있기 때문에 문서는 올바르게로드됩니다. 이 쿼리가 비어 있습니다.
Dim foo = Kml.Descendants("Document")
Dim foo = Kml.Descendants("Folder")
누군가 나를 올바른 방향으로 가리킬 수 있습니까? Good LINQ ~ XML 튜토리얼 링크에 대한 보너스 포인트 - 온라인에서 찾은 튜토리얼은 매우 간단한 시나리오에서 중지됩니다.
해결책 2
Spoon16과 Bruce Murdock에게 감사합니다. Spoon16이 게시 한 코드는 작동하지만 모든 단일 요소 이름으로 네임 스페이스를 연결하도록 강요합니다.
나는 조금 더 검색을 수행했고 이것이 어떻게 해야하는지 알아 냈습니다. 이것은 매우 간결하며 XML 요소를 참조하기위한 새로운 <...> 브래킷 구문을 좋아합니다.
Imports <xmlns:g='http://earth.google.com/kml/2.0'>
Imports System.Xml.Linq
...
Dim Kml As XDocument = XDocument.Load(Server.MapPath("../kmlimport/ga.kml"))
For Each Placemark As XElement In Kml.<g:Document>.<g:Folder>.<g:Placemark>
Dim Name As String = Placemark.<g:name>.Value
Next
참고 :g 첫 번째 줄에서 XMLN을 따릅니다. 이것은 당신에게 다른 곳 에서이 네임 스페이스를 참조 할 수있는 바로 가기를 제공합니다.
xnamespace 클래스에 대한 자세한 내용은 MSDN 문서.
다른 팁
이것은 C#에서 나를 위해 작동합니다 :
XDocument doc = XDocument.Load(@"TheFile.kml");
var q = doc.Descendants().Where(x => x.Name.LocalName == "Placemark");
Scott Hanselman에는 C# 기반 솔루션을 찾는 사람들을위한 간결한 솔루션이 있습니다.
또한 xnamespace를 사용하는 것은 문자열을 추가하는 것이 아니라 편리합니다. 이것은 조금 더 형식적입니다.
// This code should get all Placemarks from a KML file
var xdoc = XDocument.Parse(kmlContent);
XNamespace ns = XNamespace.Get("http://earth.google.com/kml/2.0");
var ele = xdoc.Element(ns + "kml").Element(ns + "Document").Elements(ns + "Placemark");
위의 수정 사항 중 어느 것도 그 일을하지 않았다. 자세한 내용은 내 의견을 참조하십시오. 네임 스페이스가 확실히 문제이기 때문에 Spoon16과 Bruce Murdock이 올바른 길을 가고 있다고 생각합니다.
추가 인터넷 검색 후에 나는 몇 가지 코드를 발견했습니다 이 페이지 이는 해결 방법을 제안했습니다. 원래 XML에서 XMLNS 속성을 벗기십시오.
' Read raw XML
Dim RawXml As String = ReadFile("../kmlimport/ga.kml")
' HACK: Linq to XML choking on the namespace, just get rid of it
RawXml = RawXml.Replace("xmlns=""http://earth.google.com/kml/2.0""", "")
' Parse XML
Dim Kml As XDocument = XDocument.Parse(RawXml)
' Loop through placemarks
Dim Placemarks = From Placemark In Kml.<Document>.<Folder>.Descendants("Placemark")
For Each Placemark As XElement In Placemarks
Dim Name As String = Placemark.<name>.Value
...
Next
네임 스페이스와 함께 작동하는 작업 코드를 게시 할 수 있다면 기꺼이 답변을 드릴 것입니다.
xelement 이름에 네임 스페이스를 추가해야 할 수도 있습니다.
Dim ns as string = "http://earth.google.com/kml/2.0"
dim foo = Kml.Descendants(ns + "Document")
구문 오류를 무시하고 C#에서 일합니다.
당신은 당신은 차이가있을 수 있음을 알게 될 것입니다 XElement.Name
vs XElement.Name.LocalName/
나는 보통 foreach
모든 것을 통해 XElements
문서에서 올바른 명명을 사용하는지 확인하기위한 첫 번째 단계입니다.
C# 여기 내 사용법의 발췌문이 있습니다. {}를 잊어 버린 것 같습니다.
private string GpNamespace =
"{http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions}";
var results = admldoc.Descendants(GpNamespace +
"presentationTable").Descendants().Select(
p => new dcPolicyPresentation(p));