【问题标题】:Parsing Optional Tags in C#在 C# 中解析可选标签
【发布时间】:2011-03-05 02:43:52
【问题描述】:

我正在尝试找到一种简单而巧妙的方法来满足以下要求。

我有一个这样安排的 XML 消息:

  <persons>
    <person>
       <firstName>Mike</firstName>
       <middleName>K.</middleName>
       <lastName>Kelly</lastName>
    </person>
    <person>
       <firstName>Steve</firstName>
       <lastName>David</lastName>
    </person>
    <person>
       <firstName>Laura</firstName>
       <middleName>X.</middleName>
       <lastName>Xavier</lastName>
    </person>
  </persons>

我想使用 xPath 表达式解析这个 XML。

persons/person/firstName
persons/person/middleName
persons/person/lastName

我的目标是将这样的 firstName、middleName 和 lastName 标记值存储到这样的字符串对象列表中:

firstNameList[0] = "Mike";
firstNameList[1] = "Steve";
firstNameList[2] = "Laura";

middleNameList[0] = "K.";
middleNameList[1] = null;
middleNameList[2] = "X.";

lastNameList[0] = "Kelly";
lastNameList[1] = "David";
lastNameList[2] = "Xavier";

在我的 C# 代码中,我这样做:

XmlNodeList firstNameNodeList = xmlDoc.SelectNodes("persons/person/firstName", nsmgr);
XmlNodeList middleNameNodeList = xmlDoc.SelectNodes("persons/person/middleName", nsmgr);
XmlNodeList lastNameNodeList = xmlDoc.SelectNodes("persons/person/lastName", nsmgr);

此代码的问题在于,对于中间名,我的 XML 列表中没有第二人称。所以 middleNameNodeList 返回 2 个值(K. 和 X.),但我不知道第 1 个人或第 2 个人或第 3 个人的中间名是否丢失。

我希望 SelectNodes() API 会提供一个迭代或索引 ID,因为哪个重复元素具有给定的值。

请建议我实现我需要的最简单的方法?非常感谢您的帮助,JK

【问题讨论】:

  • 你可以为没有中间名的人提供 吗?
  • @StackOverflowException,这是个好主意。在这种情况下,SelectNodes() 在这个例子中会返回 3 个值吗? K., null 和 X.?我需要试验一下。
  • 是的。第二个 middleName 不会为空,但 XmlNodeListInnerXml 将为空。看我的回答:)
  • 这必须是一个片段吗? XmlSerializer 和声明的类型可以为您工作吗?

标签: c# tags optional selectnodes


【解决方案1】:

这个怎么样?

foreach (Node person in xmlDoc.SelectNodes("persons/person", nsmgr))
{
    firstNameNodeList.Add(person.SelectSingleNode("firstName", nsmgr));
    middleNameNodeList.Add(person.SelectSingleNode("middleName", nsmgr));
    lastNameNodeList.Add(person.SelectSingleNode("lastName", nsmgr));
}

【讨论】:

  • 我刚刚给出了示例 XML 来解释这一点,但是在我的实际系统中,我会得到一个带有预定义 xpaths 的复杂重复标签元素。所以我不知道各个标签名称,只知道 XPath 表达式。我想尽可能通用。还有其他想法吗?
  • @JKK:没有保证节点列表是有序的。你不能假设,比方说,所有节点列表中的第三个元素属于同一个“人”。因此,Jollymorphic 的上述答案是可行的方法。
【解决方案2】:

不获取名称列表,请尝试获取persons 的列表,然后迭代该列表并获取他们的姓名。

【讨论】:

    【解决方案3】:

    您只需要遍历 persons/person 并单独处理每个 - 这会起作用:

    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load(@"test.xml");
    var persons = xmlDoc.SelectNodes("persons/person");
    foreach (XmlNode person in persons)
    {
        string firstName = person.SelectSingleNode("firstName").InnerText;
        string middleName = (person.SelectSingleNode("middleName") != null) 
                            ? person.SelectSingleNode("middleName").InnerText 
                            : null;
        string lastName = person.SelectSingleNode("lastName").InnerText;
    }
    

    【讨论】:

      【解决方案4】:

      试试

         <persons>
          <person>
             <firstName>Mike</firstName>
             <middleName>K.</middleName>
             <lastName>Kelly</lastName>
          </person>
          <person>
             <firstName>Steve</firstName>
             <middleName /> 
             <lastName>David</lastName>
          </person>
          <person>
             <firstName>Laura</firstName>
             <middleName>X.</middleName>
             <lastName>Xavier</lastName>
          </person>
        </persons>
      
      <person>
         <firstName>Steve</firstName>
         <middleName /> 
         <lastName>David</lastName>
      </person>
      

      这应该为 InnnerText 返回 "K","","X"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-26
        • 1970-01-01
        相关资源
        最近更新 更多