【问题标题】:Select a specific range of elements?选择特定范围的元素?
【发布时间】:2011-08-15 14:09:24
【问题描述】:

我想在我的 XML 文件中选择特定范围的元素

这是一个 XML 示例:

<urlset>
    <url>
        <loc>e1</loc>
        <priority>1</priority>
    </url>
    <url>
        <loc>e2</loc>
        <priority>2</priority>
    </url>
    <url>
        <loc>e3</loc>
        <priority>1</priority>
    </url>
    <url>
        <loc>e4</loc>
        <priority>3</priority>
    </url>
    <url>
        <loc>e4</loc>
        <priority>1</priority>
    </url>
    <url>
        <loc>e5</loc>
        <priority>2</priority>
    </url>
</urlset>

如何获取e2e4的值?

【问题讨论】:

  • 你有没有尝试过?
  • 按值,你的意思是优先级吗?
  • 在 [] 括号中查找 XPath 和条件 ...

标签: c# .net xml linq xpath


【解决方案1】:
var doc = XDocument.Parse(xml);

var result = doc.Element("urlset").Elements("url")
    .SkipWhile(x => x.Element("loc").Value != "e2")
    .TakeWhile(x => x.Element("loc").Value != "e4");

【讨论】:

  • 它不会只返回所有e2s 而没有别的吗?顺便说一句,我没有投票,我只是取消了我的投票(这是为了使用SkipWhileTakeWhile - 我不知道这些)。 OP 想要从 e2 到 e4 的一系列元素(例如,大概包括 e3)
  • @Morawski,它将在提供的样本中返回e2e3,换句话说,从e2e4
  • 我会考虑使用 OrderBy,Morawski 的回答也是如此。尽管在示例元素中是有序的,但可能并非如此(应由 OP 清除)。编辑: TakeWhile 不会采用最后一个元素(e4),只是检查过。此外,您应该选择获取感兴趣的值而不是 XElement。
【解决方案2】:
var result = urlset.Elements("url").Where(url =>
            url.Element("loc").Value.ToString().CompareTo("e2") >= 0 &&
            url.Element("loc").Value.ToString().CompareTo("e4") <= 0).Select(element => element.Element("loc").Value.ToString());

它使用标准(字符串)比较 - 与字母排序相同,它不能保护您免受某些元素根本没有 loc 子元素的情况(将引发空引用异常)。

【讨论】:

  • 我应该使用CompareTo (>= 不适用于字符串) - 我更新了这个。至于您的评论:我刚刚对其进行了测试,并且无论 xml 元素是否已排序,它都能按预期工作。上面给出的示例包含“e4”,如果不打算这样做,只需使用("e4") &lt; 0 而不是&lt;=。不过,它确实不如 SkipWhile / TakeWhile 干净。
  • 如果您想检索整个 XML 元素而不是单独检索 loc 值,请去掉 Select
  • e3 更改为 e10。它不会选择e10。据我了解,OP 需要 e2e4 之间的元素。
  • 我们是否希望它选择e10e10 不在 e2e4 之间。如果您有e30(被视为字符串,它确实介于e2e4 之间),则会出现问题。但是无论你使用Where还是SkipWhile/TakeWhile都会出现这个问题,这里没有区别。需要一个将"e30" 转换为(int)30"e4"(int)4 等的小方法。
  • 也许我误解了 OP 问题。据我了解,例如,1, 2, 10, 3, 4, 5 OP 需要24 之间的元素。在此示例中:2, 10, 3.
【解决方案3】:

您可以使用这个 XPath:

//url[loc = 'e2' or 
    (preceding-sibling::url/loc = 'e2' and following-sibling::url/loc = 'e4')
]

它将选择urlloc = e2, e3, e4

【讨论】:

    【解决方案4】:

    另一种方式:

    var urls = from url in doc.Descendants("urlset").Elements("url")
        let str = Int32.Parse(url.Element("loc").Value.Replace("e",""))
        where str >= 2 && str <= 4  
        select url;
    

    或者实际上,如果 loc 不是 "e + 整数值" (courtesy of Marc Gravell) 形式,则不会引发异常的更安全的选项是:

    int? TryParse(string s)
    {
        int i;
        return int.TryParse(s, out i) ? (int?)i : (int?)null;
    }
    
    var urls = from url in doc.Descendants("urlset").Elements("url")
        let str = TryParse(url.Element("loc").Value.Replace("e",""))
        where str >= 2 && str <= 4  
        select url;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多