【问题标题】:Extracting data from a complex XML with LINQ使用 LINQ 从复杂的 XML 中提取数据
【发布时间】:2012-10-25 16:39:20
【问题描述】:

我的目标是将 ValueReference 节点、TimeInstant 属性和 timePosition 节点中包含的数据保存到变量中。我能够获得 valueReference 节点的值(未注释部分有效),但不能获得其他两个。 任何帮助将不胜感激。

这是我正在处理的代码:

public void LinqToXml()
{
    XNamespace sosNamespace = XNamespace.Get("http://www.opengis.net/sos/2.0");
    XNamespace fesNamespace = XNamespace.Get("http://www.opengis.net/fes/2.0");
    XNamespace gmlNamespace = XNamespace.Get("http://www.opengis.net/gml/2.0");
    var root = XElement.Load(@"C:\Working Directory\OGCSOS.Service\OGCSOS.Service\Resources\GetObservation_TemporalFilter.xml");
    var a = (from level in root.Descendants(sosNamespace + "temporalFilter")
             select new
             {
                 valueReference = (string)level.Descendants(fesNamespace + "After")
                                               .Elements(fesNamespace + "ValueReference")
                                               .First(),
                 /*timeInstant = (string)level.Descendants(fesNamespace + "After")
                                               .Elements(gmlNamespace + "TimeInstant")
                                               .Attributes(gmlNamespace + "id")
                                               .First()*/
                 /*timePosition = (string)level.Descendants(fesNamespace + "After")
                                             .Elements(gmlNamespace + "TimeInstant")
                                             .First()*/
             }).ToList();

这是我要阅读的 XML:

    <?xml version="1.0" encoding="UTF-8"?>
<sos:GetObservation xmlns="http://www.opengis.net/sos/2.0" service="SOS" version="2.0.0" 
                    xmlns:sos="http://www.opengis.net/sos/2.0" xmlns:fes="http://www.opengis.net/fes/2.0" 
                    xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:swe="http://www.opengis.net/swe/2.0" 
                    xmlns:swes="http://www.opengis.net/swes/2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/sos/2.0
http://schemas.opengis.net/sos/2.0/sos.xsd">

    <!--identifier of an offering-->
    <offering>HG.Logger@DJK001</offering>

    <!--identifier of an observed property-->
    <observedProperty>HG</observedProperty>

    <!--optional temporal filter restricting the results which shall be returned-->
    <temporalFilter>
        <fes:After>
            <fes:ValueReference>phenomenonTime</fes:ValueReference>
            <gml:TimeInstant gml:id="startPosition">
                <gml:timePosition>2008-03-01T17:44:15.000+00:00</gml:timePosition>
            </gml:TimeInstant>
        </fes:After>
    </temporalFilter>

    <featureOfInterest>DJK001</featureOfInterest>

</sos:GetObservation>

【问题讨论】:

  • 另外,如果有人可以建议一种可能更容易的替代方法,我会全力以赴。
  • 可以有多个temporalFilter
  • 好吧,XNamespace sosNamespace = XNamespace.Get("http://www.opengis.net/sos/2.0"); 可以缩短为 XNamespace sosNamespace = "http://www.opengis.net/sos/2.0";。由于XNamespace 类背后的想法是使用实​​例通过连接构造XNames,因此我将使用一个短变量名,例如XNamespace sos = "http://www.opengis.net/sos/2.0";,然后在调用轴方法时,您的表达式会更短,例如foo.Elements(sos + "Bar").
  • 暂时只有一个时间过滤节点。
  • @MartinHonnen 感谢您的建议,我会做出更改。

标签: c# .net xml linq linq-to-xml


【解决方案1】:

您的 gml 命名空间不正确,将其更改为

 XNamespace gmlNamespace = XNamespace.Get("http://www.opengis.net/gml/3.2");

你可以使用

timeInstant = level.Descendants(fesNamespace + "After")
                   .First()
                   .Element(gmlNamespace + "TimeInstant")
                   .Attribute(gmlNamespace + "id")
                   .Value,

timePosition = level.Descendants(fesNamespace + "After")
                    .First()
                    .Element(gmlNamespace + "TimeInstant")
                    .Value

【讨论】:

    【解决方案2】:

    你应该这样做

    XNamespace sosNamespace = "http://www.opengis.net/sos/2.0";
    XNamespace fesNamespace = "http://www.opengis.net/fes/2.0";
    XNamespace gmlNamespace = "http://www.opengis.net/gml/3.2";
    //you had used 2.0 instead of 3.2
    var root = XElement.Load(@"C:\WorkingDirectory\OGCSOS.Service\OGCSOS.Service\Resources\GetObservation_TemporalFilter.xml");
    var yourList=root.Descendants(sosNamespace+"temporalFilter").Descendants(fesNamespace+"After").Select(x=>
    new
    {
    ValueReference=x.Element(fesNamespace+"ValueReference").Value,
    timeInstant=x.Element(gmlNamespace+"TimeInstant").Attribute(gmlNamespace+"id").Value,
    timePosition=x.Element(gmlNamespace+"TimeInstant").Element(gmlNamespace+"timePosition").Value
    }
    );
    

    yourList 包含所有数据

    【讨论】:

      【解决方案3】:

      你也可以使用旧的 XPath

          var doc = new XPathDocument("1.xml");
          var nav = doc.CreateNavigator();
          var mng = new XmlNamespaceManager(nav.NameTable);
          mng.AddNamespace("sos", "http://www.opengis.net/sos/2.0");
          mng.AddNamespace("fes", "http://www.opengis.net/fes/2.0");
          mng.AddNamespace("gml", "http://www.opengis.net/gml/3.2");
          var valueReference = nav.SelectSingleNode("//sos:GetObservation/sos:temporalFilter/fes:After/fes:ValueReference[1]", mng).TypedValue;
          var TimeInstant = nav.SelectSingleNode("//sos:GetObservation/sos:temporalFilter/fes:After/gml:TimeInstant/@gml:id", mng).TypedValue;
          var timePosition = nav.SelectSingleNode("//sos:GetObservation/sos:temporalFilter/fes:After/gml:TimeInstant/gml:timePosition[1]", mng).TypedValue;
      

      【讨论】:

      • 我也试了一下,但我觉得我学习 LINQ 太深入了,无法继续。谢谢你的好例子。
      【解决方案4】:

      试试这个代码:

      XmlDocument xmlSnippet = new XmlDocument();
       xmlSnippet.Load(@"C:\Working Directory\OGCSOS.Service\OGCSOS.Service\Resources\GetObservation_TemporalFilter.xml");
      
       //Selects all the similar nodes by tag Name.......
                     XmlNodeList xmlSnippetNodes = xmlSnippet.GetElementsByTagName("fes:After");
      
       //Checking if any any xmlSnippetNode has matched.
                     if (xmlSnippetNodes != null)
                     {
                         //Checks if the matched xmlSnippetNode that has fes:After attribute is not  NULL
      
      
      //Stores the value of the matched tag.
                                var valueReference= xmlSnippetNodes.Item(0).Value;
      
                         var timeInstance=xmlSnippetNodes.Item(1).Attributes["gml:id"].Value;
                       var timePosition =xmlSnippetNodes.Item(1).InnerXml.Name;
      
      
                                 //Return True if updated correctly.
                                 isUpdated = true;
      
      
                         }
      

      【讨论】:

        猜你喜欢
        • 2016-05-18
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        • 1970-01-01
        • 2023-01-26
        • 1970-01-01
        • 2013-05-19
        • 1970-01-01
        相关资源
        最近更新 更多