2015-08-09 4 views
0

Я пытаюсь присоединиться к двум файлам XML, ключ соединения иногда приходит как элемент, но иногда приходит как атрибут, как в XML-файлах ниже. Как я могу использовать XPath или || оператора для решения проблемы? Любые другие решения также очень ценятся. Спасибо заранее!Как использовать xpath в Linq для проверки элементов и атрибутов

один файл:

<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> 

Моя текущая операция присоединения основана на этом вопросе Compare elements from two xml documents based on element value in C#

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") 
         ); 

ответ

2

Вы можете выразить свою логику для извлечения элемента или атрибута в условии объединения:

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") 
    ); 
2

Вы можете использовать null coalescing operator ?? для проверки первого наличия атрибута с именем "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") 
           ); 
0

Попробуйте

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

См. fiddle

Смежные вопросы