提取属性等于特定值的元素的值

本文关键字:元素 于特定 属性 提取 | 更新日期: 2023-09-27 18:10:42

我又一次被XDocument难住了。我试图提取温度元素(12在这个例子中)的值时,类属性有一个值="高"(和"低")

我的XML的一个子集:

<forecastGroup>
    <forecast>
      <temperatures>
          <textSummary>Low plus 2. High 12.</textSummary>
          <temperature unitType="metric" units="C" class="high">12</temperature>
          <temperature unitType="metric" units="C" class="low">2</temperature>
      </temperatures>
    </forecast>
    ...etc.
    <forecast>
          <temperature unitType="metric" units="C" class="high">15</temperature>
          <temperature unitType="metric" units="C" class="low">3</temperature>
    </forecast>
<forecastGroup>

目前代码:

XDocument loaded = XDocument.Parse(strInputXML);
foreach (var forecast in loaded.Descendants("forecastGroup").Elements("forecast"))
{
   //existing code doing stuff here using the XDocument loaded
   High = "this is where I'm lost";
}

我似乎已经尝试了尝试选择"元素,属性和后代"的每一个组合,但我在一个损失。

提取属性等于特定值的元素的值

您可以在Linq to XML查询中添加Where()过滤器:

XDocument loaded = XDocument.Parse(strInputXML);
var matchingForecasts = loaded.Descendants("temperature")
                              .Where(x => (string)x.Attribute("class") == "high");
foreach (var forecast in matchingForecasts)
{
    //do something
    string temperature = forecast.Value;
}

或者,您可以查看foreach循环中的每个class属性值,这更接近您的原始方法:

foreach (var forecast in loaded.Descendants("temperature"))
{
    //existing code doing stuff here using the XDocument loaded
    if (forecast.Attribute("class").Value == "high")
    {
        //do something
        string temperature = forecast.Value;
    }
}

要在循环中提取高点,可以使用

var high = (int)forecast.Element("temperatures")
                        .Elements("temperature")
                        .Where(temp => temp.Attribute("class").Value == "high")
                        .First();

当然,您可以使用Linq-to-XML简单地将整个XML树投影到适当的对象图中,而不需要在循环中显式地将其分开,但是您应该能够朝着这个方向前进。它最终可能看起来像

var forecasts = from forecast in loaded.Descendants("forecast")
                let temps = forecast.Element("temperatures")
                let high = temps.Elements("temperature").Where(t => t.Attribute("class").Value == "high").First()
                let low = temps.Elements("temperature").Where(t => t.Attribute("class").Value == "low").First()
                select new
                {
                    Temperatures = new
                    {
                        Summary = temps.Element("textSummary").Value,
                        High = new
                        {
                            UnitType = high.Attribute("unitType").Value,
                            Units = high.Attribute("units").Value,
                            Value = (int)high
                        },
                        Low = new
                        {
                            UnitType = low.Attribute("unitType").Value,
                            Units = low.Attribute("units").Value,
                            Value = (int)low
                        },
                    }
                };
loaded.Descendants("temperature")
.Where(d => d.Attribute("class").Value.Equals("high")).First().Value

示例XML文件将无法工作,因为它没有正确关闭。

 <forecastGroup>
    <forecast>
      <temperatures>
          <textSummary>Low plus 2. High 12.</textSummary>
          <temperature unitType="metric" units="C" class="high">12</temperature>
          <temperature unitType="metric" units="C" class="low">2</temperature>
      </temperatures>
    </forecast>
    ...etc.
    <forecast>
          <temperature unitType="metric" units="C" class="high">15</temperature>
          <temperature unitType="metric" units="C" class="low">3</temperature>
    </forecast>
<forecastGroup>   // <= this needs to be </forecastGroup>

您可以尝试这样使用XPath:

using System.Xml.XPath;
...
string xpathExpression = "forecastGroup/forecast//temperature[@class='high']";
foreach (XElement el in loaded.XPathSelectElements(xpathExpression))
{
    int highTemperature = Int32.Parse(el.Value);
}

搜索表达式可以更短("//temperature[@class='high']"),但更详细地说明值的位置会更有效。

如果想用'high'或'low'类属性值过滤温度,可以使用以下xpath表达式:

"forecastGroup/forecast//temperature[@class='high' or @class='low']"

如果您想根据@class属性决定要做什么,您可以使用以下代码:

string xpathExpression = "forecastGroup/forecast//temperature[@class='high' or @class='low']";
foreach (XElement el in loaded.XPathSelectElements(xpathExpression))
{
    int temperature = Int32.Parse(el.Value);
    if (el.Attribute("class").Value == "low")
    {
        // do sth with low value
    }
    else
    {
        // do sth with high value
    }
}