我有一个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>
的节点下。
答案 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;
}
我的想法如下:
templateId
元素中有root
属性的唯一一个(或null)value
元素下的reference
元素提取value
属性。答案 2 :(得分:0)
您可能必须在LINQ中包含命名空间。要检索它,你会做这样的事情:
XNamespace ns = xdoc.Root.GetDefaultNamespace();
然后在你的linq:
var obsvlookfor = xdoc.Root.Descendants(ns + "observation")
我知道如果没有这个,我有一些问题需要检索一次数据。不要说它的问题只是要记住,特别是如果您的XML文件非常深入。