为什么 XPath 表达式返回一个只有一个子元素的元素?

Why is an XPath expression returning an element with just one child?

提问人:SNBS 提问时间:11/6/2023 更新时间:11/6/2023 访问量:35

问:

我有这个XML文件。它包含 MSBuild 导出的 C# 文档注释(如果相关)。

<?xml version="1.0"?>
<doc>
  <assembly>
    <name>Test</name>
  </assembly>
  <members>
    <member name="T:Test.TestClass`2">
      <summary>
        This is just a test class.
      </summary>
      <typeparam name="T1">A generic parameter.</typeparam>
      <typeparam name="T2">Another generic parameter.</typeparam>
      <remarks>
        It is used to test the library.

        <typeparamref name="T1"/> is a very nice generic parameter.
      </remarks>
      <seealso>
        Don't see also
      </seealso>
    </member>
    <member name="P:Test.TestClass`2.TestProperty">
      <summary>
        This is a property of the <see cref="T:Test.TestClass"/> class.
      </summary>
      <value>
        Always returns 0.
      </value>
      <seealso>
        Don't see also
      </seealso>
    </member>
    <member name="M:Test.TestClass`2.Generic`1(System.Int32,System.Collections.Generic.List{`0},System.Collections.Generic.List{`3})">
      <summary>
        Test of the generic parameters handling.
      </summary>
    </member>
    <member name="M:Test.TestClass`2.DoTheJob(System.String,System.Int32)">
      <param name="str">A string.</param>
      <param name="integer">A 32-bit integer.</param>
      <remarks>
        A dummy method. Don't pass 3 to <paramref name="integer"/>.
      </remarks>
    </member>
    <member name="T:Test.AnotherTestClass">
      <summary>
        A nice little class.
      </summary>
    </member>
    <member name="E:Test.AnotherTestClass.MyEvent">
      <summary>
        Occurs very frequently.
      </summary>
      <example>
        anotherTestClass.MyEvent += MyHandler;
      </example>
    </member>
    <member name="F:Test.AnotherTestClass.StructureOfTheWorld">
      Some idiot put this text here.
      <summary>
        Contains the <c>structure</c> of the world.
      </summary>
      <remarks>
        Includes:

        <list type="bullet">
          <item>
            <term>Stars</term>
            <description>Large shining spheres</description>
          </item>
          <item>
            <term>Planets</term>
            <description>Smaller spheres that go around stars</description>
          </item>
          <item>
            <term>Planets</term>
            <description>Smaller spheres that go around stars</description>
          </item>
          <item>
            <term>Black holes</term>
            <description>Very curious objects</description>
          </item>
        </list>
      </remarks>
    </member>
    <member name="M:Test.AnotherTestClass.#ctor(System.Type)">
      <summary>
        This is a constructor.
      </summary>
      <seealso>
        <list type="bullet">
          <item>I</item>
          <item>Mum</item>
          <item>Dad</item>
          <item>Grandad</item>
          <item>Grandma</item>
          <item>Brother</item>
          <item>Sister</item>
        </list>
      </seealso>
    </member>
    <member name="M:Test.AnotherTestClass.op_Implicit(Test.AnotherTestClass)~System.String">
      <summary>
        Just calls ToString().
      </summary>
      <remarks>
        Do not use.
      </remarks>
    </member>
  </members>
</doc>

我想逐个检查元素,按名称搜索它们。我正在使用这个 XPath 表达式:member

//member[@name='{insert_name_to_be_inspected_here}']

这有效,但由于某种奇怪的原因,它返回的元素只有一个子元素,即使有更多子元素。member

如果我搜索 ,它将返回以下 XML(缩进被精确复制):T:Test.AnotherTestClass

<summary>
        A nice little class.
      </summary>

如果我搜索 ,它会返回以下内容:T:Test.TestClass`2

<summary>
        This is just a test class.
      </summary>

那么 等元素在哪里呢?remarkstypeparam

xml xpath

评论

0赞 LMC 11/6/2023
这取决于用于分析 xml 的语言和代码。没有这个,就很难说了。
0赞 Yitzhak Khabinsky 11/6/2023
在提出问题时,您需要提供一个最小的可重现示例:请编辑您的原始问题并提供以下内容:(1) 格式正确的 XML 文件示例。(2)你需要做什么,即逻辑,以及你的代码尝试实现它。(3) 基于上述 #1 中的示例数据的所需输出。所有问题都是文本,没有图像。

答:

0赞 Michael Kay 11/6/2023 #1

但是由于某种奇怪的原因,它返回的成员元素只有一个子元素

你怎么知道?它告诉你它只有一个子元素是什么?在我看来,XPath 表达式更有可能返回正确的结果,并且随后在显示或检查此结果的方式中出现问题。

1赞 Yitzhak Khabinsky 11/6/2023 #2

没有提供最小的可重现示例。所以,我是从臀部射击的。

请在下面找到基于 LINQ to XML API 的解决方案。自 2007 年以来,它在 .Net Framework 中可用。

c#

void Main()
{
    const string xmlFile = @"e:\Temp\SNBS.xml";
    string memeberName = "T:Test.TestClass`2";
    
    XDocument xdoc = XDocument.Load(xmlFile);

    var xelem = xdoc.Descendants("member")
      .Where(x => x.Attribute("name").Value == memeberName);
      
    Console.WriteLine(xelem);
}

输出

<member name="T:Test.TestClass`2">
  <summary>This is just a test class.</summary>
  <typeparam name="T1">A generic parameter.</typeparam>
  <typeparam name="T2">Another generic parameter.</typeparam>
  <remarks>It is used to test the library.

                <typeparamref name="T1" />is a very nice generic parameter.</remarks>
  <seealso>Don't see also</seealso>
</member>

评论

0赞 SNBS 11/7/2023
谢谢。前往 XPath 完成如此简单的任务可能不是很聪明。
0赞 Yitzhak Khabinsky 11/7/2023
很高兴听到建议的解决方案对您有用。请将其标记为已回答。您只需要将答案标记为正确(绿色复选图像)。单击已解决问题的答案左侧的绿色勾选标记。这会将答案标记为“已接受”
0赞 SNBS 11/8/2023
我认为从我的 >200 声誉中可以明显看出,我知道如何接受答案。不过我没有这样做,因为我在看到它后无法立即尝试解决方案。