如何在Linq中使用xpath来检查元素和属性

本文关键字:检查 元素 属性 xpath Linq | 更新日期: 2023-09-27 18:07:06

我试图连接两个XML文件,连接键有时作为元素出现,但有时作为属性出现,如下面的XML文件所示。如何使用XPath或运算符来解决这个问题?任何其他的解决方案都是非常赞赏的。提前感谢!

文件:

<bookstore>
   <book>
     <bookID>100</bookID>
     <name> The cat in the hat </name>
   </book>
   <book>
     <bookID>90</bookID>
     <name> another book </name>
   </book>
   <book>
     <bookID>103</bookID>
     <name> a new book </name>
   </book>
</bookstore>

文件二,在这里连接键bookID是属性:

 <bookstore>
  <book bookID=100>
    <content> story </content>
  </book>
  <book bookID=90>
    <content> fiction </content>
  </book>
  <book bookID=103>
    <content> bio </content>
  </book>

我想要的结果是

<result>
<bookInfo>
   <bookID>103</bookID>
   <name> a new book </name>
   <content> bio </content>
<bookInfo>
</result>

我当前基于这个问题的连接操作基于c#中的元素值比较两个xml文档中的元素

    var bookInfos =
          from a in fileone.Descendants("book")
          join b in filetwo.Descendants("book")
              on (string)a.Element("bookID") equals  (string)b.Element("bookID") //how can I change the Join condition as the key might attributes in any of the two files? 
    select new XElement("bookInfo", 
                            a.Element("bookID"), 
                            a.Element("name"), 
                            b.Element("content")
                        );

如何在Linq中使用xpath来检查元素和属性

可以使用空合并操作符??首先检查是否存在名为"bookID"的属性,如果不存在,则检查该名称的元素:

        var bookInfos =
              from a in fileone.Descendants("book")
              join b in filetwo.Descendants("book")
                  on ((string)a.Attribute("bookID") ?? (string)a.Element("bookID")) equals ((string)b.Attribute("bookID") ?? (string)b.Element("bookID"))
              select new XElement("bookInfo",
                                      new XElement("bookID", (string)a.Attribute("bookID") ?? (string)a.Element("bookID")),
                                      a.Element("name"),
                                      b.Element("content")
                                  );

您可以在连接条件中表达检索元素或属性的逻辑:

var bookInfos =
    from a in fileone.Descendants("book")
    let aBookID = (string)a.Element("bookID") ?? (string)a.Attribute("bookID")
    join b in filetwo.Descendants("book")
        on aBookID equals (string)b.Element("bookID") ?? (string)b.Attribute("bookID")
    select new XElement("bookInfo",
        aBookID,
        a.Element("name"),
        b.Element("content")
    );

试试这个

on (string)a.Element("bookID") equals (string)(b.Attribute("bookID")) 

看到小提琴