Przetwarzam tekst XML przy użyciu Linq to XML. Zwrócony XDocument dodaje całą tę przestrzeń nazw do każdego z moich węzłów i uniemożliwia znalezienie potomków lub przynajmniej moje wyszukiwanie „Placemark” nie działa, najprawdopodobniej dlatego, że kml:Placemark nie pasuje do wyszukiwania.

Kiedy przetestowałem to w teście jednostkowym, z podstawowym plikiem XML, zadziałało dobrze. Zgaduję, że część deklaracji XML nie miała wszystkich przestrzeni nazw.

Jak mogę przeanalizować tekst XML bez dodawania wszystkich przestrzeni nazw?

Rozbiór gramatyczny zdania:

    XDocument document = XDocument.Parse(text);
    var polygonNodes = document.Descendants("Polygon"); // yields no nodes, even though there are descendants with this.

oryginalny plik

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
    <name>poly1_philmont.kml</name>
    <Style id="s_ylw-pushpin_hl">
        <IconStyle>
            <scale>1.3</scale>
            <Icon>
                <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
            </Icon>
            <hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
        </IconStyle>
        <LineStyle>
            <color>ff0000aa</color>
        </LineStyle>
        <PolyStyle>
            <color>33ffaa00</color>
        </PolyStyle>
    </Style>
... </kml>

Przeanalizowano za pomocą XDocument (węzeł główny)

<kml:kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
  <kml:Document>
    <kml:name>poly1_philmont.kml</kml:name>
    <kml:Style id="s_ylw-pushpin_hl">
      <kml:IconStyle>
        <kml:scale>1.3</kml:scale>
        <kml:Icon>
          <kml:href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</kml:href>
        </kml:Icon>
        <kml:hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
      </kml:IconStyle>
      <kml:LineStyle>
        <kml:color>ff0000aa</kml:color>
      </kml:LineStyle>
      <kml:PolyStyle>
        <kml:color>33ffaa00</kml:color>
      </kml:PolyStyle>
    </kml:Style>
...
</kml:kml>
1
Stealth Rabbi 28 sierpień 2012, 16:52

2 odpowiedzi

Najlepsza odpowiedź

Myślę, że masz problem z modelem danych LINQ to XML, nie przechowuje on części prefiksu elementu lub nazwy atrybutu w swoim modelu, zamiast tego po prostu przechowuje atrybuty deklaracji przestrzeni nazw (np. xmlns="..." i xmlns:pf="..."), a następnie podczas serializacji drzewa obiektów w celu oznaczenia, próbuje wywnioskować prefiks dla elementów i atrybutów. W twoim przykładzie przestrzeń nazw http://www.opengis.net/kml/2.2 jest zdefiniowana dwukrotnie, raz jako domyślna przestrzeń nazw z xmlns="http://www.opengis.net/kml/2.2", raz z prefiksem kml (xmlns:kml="http://www.opengis.net/kml/2.2"). W takim przypadku próba wywnioskowania prefiksu dla nazw elementów jest zepsuta, wygląda na to, że implementacja bierze pod uwagę ostatnią deklarację jako

    string xml = @"<foo xmlns=""http://example.com/ns1"" xmlns:pf=""http://example.com/ns1""/>";

    XDocument doc = XDocument.Parse(xml);

    doc.Save(Console.Out);

Wyjścia

<pf:foo xmlns="http://example.com/ns1" xmlns:pf="http://example.com/ns1" />

Podczas

    string xml = @"<foo xmlns:pf=""http://example.com/ns1"" xmlns=""http://example.com/ns1""/>";

    XDocument doc = XDocument.Parse(xml);

    doc.Save(Console.Out);

Wyjścia

<foo xmlns:pf="http://example.com/ns1" xmlns="http://example.com/ns1" />

Jeśli więc nie kontrolujesz kolejności deklaracji przestrzeni nazw, gdy dane wejściowe są tworzone, wejściowy kod XML z dwiema deklaracjami przestrzeni nazw dla tej samej przestrzeni nazw może nie działać w obie strony z XDocument lub XElement.

Niemniej jednak tak długo, jak elementy znajdują się w przestrzeni nazw, właściwym sposobem z LINQ to XML, aby uzyskać do nich dostęp za pomocą metody Descendants lub Elements lub Element jest użycie konkatenacji XNamespace z string do skonstruowania XName eg

XNamespace ns = doc.Root.Namespace;
IEnumerable<XElement> fooElements = doc.Descendants(ns + "foo");
2
Martin Honnen 28 sierpień 2012, 18:34

Użyj tego

XNamespace kmlNS = "http://www.opengis.net/kml/2.2";
XDocument document = XDocument.Parse(text);
var polygonNodes = document.Descendants(kmlNS+"Polygon");
0
Parv Sharma 28 sierpień 2012, 16:56