LINQ to XML查询取决于后代的标记名称

时间:2012-11-02 18:28:28

标签: c# xml xml-parsing linq-to-xml

我有以下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>2010-07-31T01:05:00</gml:timePosition>
            </gml:TimeInstant>
        </fes:After>
    </temporalFilter>

    <featureOfInterest>DJK001</featureOfInterest>

</sos:GetObservation>

<temporalFilter>节点可以替换为:

<temporalFilter>
    <fes:Before>
        <fes:ValueReference>phenomenonTime</fes:ValueReference>
        <gml:TimeInstant gml:id="endPosition">
            <gml:timePosition>2010-07-31T01:05:00</gml:timePosition>
        </gml:TimeInstant>
    </fes:Before>
</temporalFilter>

或者:

<temporalFilter>
    <fes:During>
        <fes:ValueReference>phenomenonTime</fes:ValueReference>
        <gml:TimePeriod gml:id="duringPosition">
            <gml:beginPosition>2010-07-31T01:05:00</gml:beginPosition>
            <gml:endPosition>2010-07-31T01:06:00</gml:endPosition>
        </gml:TimePeriod>
    </fes:During>
</temporalFilter>

以下LINQ to XML代码工作,但我需要代码能够处理上面列出的三种temporalFilter可能性中的任何一种。有人有什么建议吗?

private void GetTemporalFilterFromXml(GetObservation getObservation)
    {
        //var root = XElement.Load(@"C:\Working Directory\OGCSOS.Service\OGCSOS.Service\Resources\GetObservation_TemporalFilter.xml");
        var root = XElement.Parse(getObservation.ToXml(false, Formatting.None, EOLType.CRLF, RequestHandler.GetSos20Context()));
        GetTemporalFilterDescendant(root); //Test line of code!
        var query = (from level in root.Descendants(sos + "temporalFilter")
                     select new
                     {
                         valueReference = (string)level.Descendants(fes + "ValueReference").FirstOrDefault(),
                         timeInstant = (string)level.Descendants(gml + "TimeInstant").First().Attribute(gml + "id"),
                         timePosition = (string)level.Descendants(gml + "TimeInstant").Descendants(gml + "timePosition").First()
                     }).ToList();
        if (query.Any() == false) return;
        if (!String.IsNullOrEmpty(query[0].valueReference)) ValueReference = query[0].valueReference;
        if (!String.IsNullOrEmpty(query[0].timePosition)) TimePosition = query[0].timePosition;
        if (!String.IsNullOrEmpty(query[0].timeInstant)) TimeInstant = query[0].timeInstant;
    }

编辑:这是我正在使用的代码,用于捕获我需要的所有数据

    {
        //var root = XElement.Load(@"C:\Working Directory\OGCSOS.Service\OGCSOS.Service\Resources\GetObservation_TemporalFilter.xml");
        var root = XElement.Parse(getObservation.ToXml(false, Formatting.None, EOLType.CRLF, RequestHandler.GetSos20Context()));
        var query = (from x in root.Descendants(sos + "temporalFilter").Elements()
                     let timeInstant = x.Element(gml + "TimeInstant")
                     let timePeriod = x.Element(gml + "TimePeriod")
                     select new
                     {
                         valueReference = (string)x.Element(fes + "ValueReference"),
                         timeInstant = (timeInstant == null) ? null : timeInstant.Attribute(gml + "id").Value,
                         timePosition = (timeInstant == null) ? null : timeInstant.Element(gml + "timePosition").Value,
                         timePeriod = (timePeriod == null) ? null : timePeriod.Attribute(gml + "id").Value,
                         beginPosition = (timePeriod == null) ? null : timePeriod.Element(gml + "beginPosition").Value,
                         endPosition = (timePeriod == null) ? null : timePeriod.Element(gml + "endPosition").Value,
                     }).ToList();

        if (query.Count == 0) return;
        ValueReference = query[0].valueReference;
        TimeInstant = query[0].timeInstant;
        TimePosition = query[0].timePosition;
        TimePeriod = query[0].timePeriod;
        BeginTime = query[0].beginPosition;
        EndTime = query[0].endPosition;
    }

1 个答案:

答案 0 :(得分:2)

这将完成这项工作。 Elements()将返回所有三种类型的节点 - Before,After和During。引入新的范围变量timeInstant可以检查元素和句柄中是否存在此节点:节点:

var query = from x in root.Descendants(sos + "temporalFilter").Elements()
            let timeInstant = x.Element(gml + "TimeInstant")
            select new 
            {
                valueReference = (string)x.Element(fes + "ValueReference"),
                timeInstant = (timeInstant == null) ? null : (string)timeInstant.Attribute(gml + "id"),
                timePosition = (timeInstant == null) ? null : (string)timeInstant.Element(gml + "timePosition")
            };

BTW 您可以将timePosition投射到(DateTime?),而Linq会为您提供漂亮的DateTime对象。