在不知道xdoc的结构的情况下,选择立即值为的元素

本文关键字:选择 元素 不知道 xdoc 结构 情况下 | 更新日期: 2023-09-27 18:05:07

更新:我完全把这个问题简单化了,把每个人都引入了错误的问题。这是实际的问题:我试图获取值与正则表达式匹配的元素。我改写了问题。。。

给定一个我不知道结构的XDocument,我如何选择所有值与正则表达式匹配的元素?

例如:

<html>
    <head></head>
    <body>
        <table>
            <tr>
                <td>{{ var1 }}</td>
                <td>{{ var2 }}</td>
            </tr>
            <tr>
                <td>{{ var3 }}</td>
                <td>{{ var4 }}</td>
            </tr>
        </table>
    </body>
</html>

我会得到html、body、table、tr和四个td元素的结果。如何选择值与此正则表达式匹配的所有元素,并只返回td元素

private Regex _placeholderRegex = new Regex("({{.+?}})");
public string GetParsedDocument(...)
{
    var placeHolders = _template
        .Descendants()
        .Where(d => _placeholderRegex.IsMatch(d.Value));
    // more stuff
    return null;
}

我最终得到了每个元素的结果,这些元素是我正在寻找的元素的祖先。。。

所以现在我想一想,我发现它只是查看每个元素的整个内容,如果其中任何地方都包含匹配项,就选择它。所以我想我只需要找到一种缩小范围的方法。

在不知道xdoc的结构的情况下,选择立即值为的元素

这是一种可能的方式:

var placeHolders = from d in mydoc.Descendants()
                   where d.DescendantNodes()
                          .OfType<XText>()
                          .Any(o => o.Parent == d && _placeholderRegex.IsMatch(o.Value))
                   select d;

上面的代码通过检查任何文本节点(即当前节点d(Parent == d(的直接子节点(是否具有与正则表达式模式匹配的值来工作。

以下是演示的工作示例:

var xml = @"<html>
    <head></head>
    <body>
        <table>
            <tr>
                <td>{{ var1 }}</td>
                <td>{{ var2 }}</td>
            </tr>
            <tr>
                <td>{{ var3 }}</td>
                <td>{{ var4 }}</td>
            </tr>
        </table>
    </body>
</html>";
var mydoc = XDocument.Parse(xml);
var _placeholderRegex = new Regex("({{.+?}})");
var placeHolders = from d in mydoc.Descendants()
                   where d.DescendantNodes()
                          .OfType<XText>()
                          .Any(o => o.Parent == d && _placeholderRegex.IsMatch(o.Value))
                   select d;
foreach (var placeHolder in placeHolders)
{
    Console.WriteLine(placeHolder.Value);
}

输出:

{{ var1 }}
{{ var2 }}
{{ var3 }}
{{ var4 }}

如果我理解正确:

  1. 如果只有td元件,则更换。上的Descendants((。后代("td"(

    var placeHolders = mydoc
                .Descendants("td")
                .Where(d => _placeholderRegex.IsMatch((string)d))
                .Select(x => (string)x);
    

链接:https://dotnetfiddle.net/eoDVWH

  1. 或者,检查子元素的存在:

    var placeHolders = mydoc
                .Descendants()
                .Where(d => !d.HasElements && _placeholderRegex.IsMatch((string)d))
                .Select(x => (string)x);
    

链接:https://dotnetfiddle.net/FEwSf3

您可以将!d.Elements().Any()添加到谓词中,只获取没有任何子级的元素:

var placeHolders = _template
    .Descendants()
    .Where(d => !d.Elements().Any() && _placeholderRegex.IsMatch((string)d))
    .ToList();