使用Linq查询XML树

时间:2012-07-03 20:01:24

标签: c# xml linq

我正在尝试使用LINQ解析出复杂的XML文件。这些文件包含数千条记录,每条记录包含数百个字段。我需要解析有关每种药物的某些信息部分并将其存储在数据库中。

修改 我很抱歉,但最初发布的XML实际上并不准确。我没有意识到这些属性会改变这个过程。我已经更新了问题,以准确描述XML文件的真实性质。

以下是XML的示例:

<<drugs xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://drugbank.ca" xs:schemaLocation="http://www.drugbank.ca/docs/drugbank.xsd" schemaVersion="1.4">
   <drug>
      <name>foo</name>
      <indication>Some info here</indication>
      <half-life>1 to 3 hours</half-life>
      <protein-binding>90%</protein-binding>
        // hundreds of other elements
      <properties>
         <property>
            <kind>logP/hydrophobicity</kind>
            <value>-0.777</value>
         </property>
         <property>
            <kind>Molecular Weight</kind>
            <value>6963.4250</value>
         </property>
         <property>
            <kind>Molecular Formula</kind>
            <value>C287H440N80O110S6</value>
         </property>
         //dozens of other properties
      </properties>
   </drug>
   // thousands of more drugs
</drugs>

我对实际查询非常模糊,因为这是我第一次使用LINQ。我熟悉SQL,所以复杂查询的概念对我来说并不困难,但我找不到任何可以帮助解决这个问题的文档。我到目前为止的查询如下:

XDocument xdoc = XDocument.Load(@"drugbank.xml");

var d = from drugs in xdoc.Descendants("drug")
                        select new
                        {
                            name = drugs.Element("name").Value,
                            indication = drugs.Element("indication").Value,
                            halflife = drugs.Element("half-life").Value,
                            proteinBinding = drugs.Element("protein-binding").Value,
                        };

第一个问题是(理论上)解决了。在... ...

第二个问题是我需要提取一些属性(即疏水性,分子量和分子式),但我感到困惑的是,属性种类和属性值存储在两个不同的XElements。如何才能将属性值限制在我关注的字段中?

2 个答案:

答案 0 :(得分:1)

我已粘贴您的代码: 输出:

foo
Some info here
1 to 3 hours
90%

正如预期的那样

答案 1 :(得分:1)

您可以执行子查询以将属性获取到外部通用对象的另一个属性中。如果你想要它们嵌套:

XNamespace defaultNS = "http://drugbank.ca";

var d = from drugs in xdoc.Descendants(defaultNS + "drug")
        select new
        {
            name = drugs.Element(defaultNS + "name").Value,
            indication = drugs.Element(defaultNS + "indication").Value,
            halflife = drugs.Element(defaultNS + "half-life").Value,
            proteinBinding = drugs.Element(defaultNS + "protein-binding").Value,
            Properties = (from property in drugs.Element(defaultNS + "properties").Elements(defaultNS + "property")
                          let kind = property.Element(defaultNS + "kind").Value
                          where kind == "logP/hydrophobicity" || kind == "Molecular Weight" || kind == "Molecular Formula"
                          select new { Kind = kind, Value = property.Element(defaultNS + "value").Value })
        };

或扁平化:

XNamespace defaultNS = "http://drugbank.ca";

var d = from drugs in xdoc.Descendants(defaultNS + "drug")
        let properties = drugs.Element(defaultNS + "properties").Elements(defaultNS + "property")
        select new
        {
            name = drugs.Element(defaultNS + "name").Value,
            indication = drugs.Element(defaultNS + "indication").Value,
            halflife = drugs.Element(defaultNS + "half-life").Value,
            proteinBinding = drugs.Element(defaultNS + "protein-binding").Value,
            hydrophobicity = (from property in properties
                          let kind = property.Element(defaultNS + "kind").Value
                          where kind == "logP/hydrophobicity"
                          select property.Element(defaultNS + "value").Value).FirstOrdefaultNS(),
            molecularWeight = (from property in properties
                          let kind = property.Element(defaultNS + "kind").Value
                          where kind == "Molecular Weight" || kind == "Molecular Formula"
                          select property.Element(defaultNS + "value").Value).FirstOrdefaultNS(),
            molecularFormula = (from property in properties
                          let kind = property.Element(defaultNS + "kind").Value
                          where kind == "Molecular Formula"
                          select property.Element(defaultNS + "value").Value).FirstOrdefaultNS()
        };

另外,一个非常有用的参考资料可以帮助您了解Linq 101 LINQ Samples