在XML中定位值

时间:2013-04-18 23:54:20

标签: c# xml linq-to-xml

我有一个xml文件加载到我需要从中提取值的XDocument中,我不确定最好的方法。我提出的大多数事情似乎都是矫枉过正或者没有充分利用xml规则。我有以下片段xml:

    <entry>
      <observation classCode="OBS" moodCode="EVN">
        <templateId root="2.16.840.1.113883.10.20.6.2.12" />
        <code code="121070" codeSystem="1.2.840.10008.2.16.4" codeSystemName="DCM" displayName="Findings">
        </code>
        <value xsi:type="ED">
          <reference value="#121071">
          </reference>
        </value>
      </observation>
    </entry>

可以有任意数量的<entry>个节点,它们都将遵循类似的模式。 root元素上的templateId属性下的值包含一个已知的UID,用于将此条目标识为我想要的条目。我需要获得参考值。

我的想法是找到正确的templateID节点,返回观察节点,找到<valuexsi:type="ED">,然后获取参考值。这看起来过于复杂,我想知道是否还有其他方法可以做到这一点?

修改

我收到的xml有时可以将xml嵌套在相同的节点名下。换句话说,<observation>可能位于另一个名为<observation>的节点下。

3 个答案:

答案 0 :(得分:1)

您遇到问题,因为您的文档使用了命名空间,而您的查询却缺少它们。

首先,您必须在XML中的某处找到xsi名称空间声明(可能在最顶层的元素中)。

看起来像这样:

xmlns:xsi="http://test.namespace"

,取名称空间Uri并根据它的值创建XNamespace实例:

var xsi = XNamespace.Get("http://test.namespace");

在查询中使用xsi变量:

var query = from o in xdoc.Root.Element("entries").Elements("entry").Elements("observation")
            let tId = o.Element("templateId")
            where tId != null && (string)tId.Attribute("root") == "2.16.840.1.113883.10.20.6.2.12"
            let v = o.Element("value")
            where v != null && (string)v.Attribute(xsi + "type") != null
            let r = v.Element("reference")
            where r != null
            select (string)r.Attribute("value");

var result = query.FirstOrDefault();

我已经测试了它的XML结构:

<root xmlns:xsi="http://test.namespace">
  <entries>
    <entry>
      <observation classCode="OBS" moodCode="EVN">
        <templateId root="2.16.840.1.113883.10.20.6.2.12" />
        <code code="121070" codeSystem="1.2.840.10008.2.16.4" codeSystemName="DCM" displayName="Findings">
        </code>
        <value xsi:type="ED">
          <reference value="#121071">
          </reference>
        </value>
      </observation>
    </entry>
  </entries>
</root>

查询返回#121071

对于输入XML,您可能需要更改第一行查询:

from o in xdoc.Root.Element("entries").Elements("entry").Elements("observation")

匹配XML结构中的<observation>元素。

答案 1 :(得分:0)

以下内容会有所帮助吗?

   XDocument xdoc = GetYourDocumentHere();
   var obsvlookfor =
       xdoc.Root.Descendants("observation")
           .SingleOrDefault(el => 
                el.Element("templateId")
                    .Attribute("root").Value == "root value to look for");

   if (obsvlookfor != null)
   {
       var reference = obsvlookfor
           .Element("value")
           .Element("reference").Attribute("value").Value;
   }

我的想法如下:

  1. 拉出文档中的所有观察元素
  2. 找出观察点templateId元素中有root属性的唯一一个(或null)
  3. 如果您找到该观察元素,请针对value元素下的reference元素提取value属性。

答案 2 :(得分:0)

您可能必须在LINQ中包含命名空间。要检索它,你会做这样的事情:

XNamespace ns = xdoc.Root.GetDefaultNamespace();

然后在你的linq:

var obsvlookfor = xdoc.Root.Descendants(ns + "observation")

我知道如果没有这个,我有一些问题需要检索一次数据。不要说它的问题只是要记住,特别是如果您的XML文件非常深入。