提取父元素位于默认命名空间中的 XML 子元素
本文关键字:元素 命名空间 XML 于默认 提取 默认 | 更新日期: 2023-09-27 18:34:03
我有下面的XML,我一直在尝试提取名字,姓氏和其他名字一段时间,现在我遇到了各种各样的问题。
<OmdCds xmlns="cds"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cdsd="cds_dt"
xsi:schemaLocation="cds ontariomd_cds.xsd">
<PatientRecord>
<Demographics>
<Names>
<cdsd:LegalName namePurpose="L">
<cdsd:FirstName>
<cdsd:Part>SARAH</cdsd:Part>
<cdsd:PartType>GIV</cdsd:PartType>
<cdsd:PartQualifier>BR</cdsd:PartQualifier>
</cdsd:FirstName>
<cdsd:LastName>
<cdsd:Part>GOMEZ</cdsd:Part>
<cdsd:PartType>FAMC</cdsd:PartType>
<cdsd:PartQualifier>BR</cdsd:PartQualifier>
</cdsd:LastName>
<cdsd:OtherName>
<cdsd:Part>GABRIELA</cdsd:Part>
<cdsd:PartType>GIV</cdsd:PartType>
<cdsd:PartQualifier>BR</PartQualifier>
我目前正在尝试使用以下 c# 代码提取,但仍然无法提取上述数据。我收到一个空引用异常。
XmlDocument doc = new XmlDocument();
doc.Load(folder + "''" + o.ToString());
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(doc.NameTable);
namespaceManager.AddNamespace("cdsd", "http://www.w3.org/2001/XMLSchema-instance");
XmlNode firstName = doc.DocumentElement.SelectSingleNode("/PatientRecord/Demographics/Names/cdsd:LegalName/cdsd:FirstName/cdsd:Part", namespaceManager);
string fName = firstName.InnerText;
MessageBox.Show(fName);
我可以在文档下的本地监视项中看到。DocumentElement,所有 InnerXML 和 InnerText。内部XML看起来像这样...
<PatientRecord xmlns='"cds'"><Demographics><Names><cdsd:LegalName namePurpose='"L'" xmlns:cdsd='"cds_dt'"><cdsd:FirstName><cdsd:Part>SARAH</cdsd:Part><cdsd:PartType>GIV</cdsd:PartType><cdsd:PartQualifier>BR</cdsd:PartQualifier></cdsd:FirstName>
文档中有 3 个命名空间定义:
-
cds
- 作为默认命名空间 -
http://www.w3.org/2001/XMLSchema-instance
- 带有xsi
前缀 -
cds_dt
- 带有cdsd
前缀
我想知道您不会收到错误消息,因为cds
和cds_dt
不是 URI,并且命名空间必须是 URI。
如果您尝试理解元素名称,则需要将前缀替换为实际命名空间。
-
<PatientRecord>
读作{cds}:PatientRecord
-
<cdsd:LegalName>
读作{cds_dt}:LegalName
现在,在 XPath 1.0 中,注册的命名空间也会发生同样的情况。但是 XPath 没有默认的命名空间。因此,没有元素的元素不会使用默认命名空间进行扩展。
您需要在命名空间管理器上注册命名空间前缀。前缀不需要与文档中的前缀相同。
namespaceManager.AddNamespace("cdsd", "cds_dt");
namespaceManager.AddNamespace("cds", "cds");
现在,您可以在 XPath 中使用已注册的命名空间:
doc.DocumentElement.SelectSingleNode(
"cds:PatientRecord/cds:Demographics/cds:Names/cdsd:LegalName/cdsd:FirstName/cdsd:Part",
namespaceManager
);
如果 XPath 表达式的第一个字符是斜杠,则该表达式相对于文档,否则相对于当前上下文节点。在doc.DocumentElement
(OmdCds
元素节点(上调用SelectSingleNode()
。 PatientRecord
是子节点,因此您可以从它开始,也可以将.
用于当前上下文节点。
PatientRecord
、 Demographics
和 Names
都在 cds
命名空间中。这是因为 OmdCds
元素 ( xmlns="cds"
( 上的默认命名空间声明。其他的在 cdsd
命名空间中,而不是 xsi
。您必须添加它们并在 XPATH 中使用它们:
namespaceManager.AddNamespace("cdsd", "cdsd");
namespaceManager.AddNamespace("cds", "cds");
XmlNode firstName = doc.DocumentElement.SelectSingleNode(
"/cds:PatientRecord/cds:Demographics/cds:Names/cdsd:LegalName/cdsd:FirstName/cdsd:Part",
namespaceManager);
顺便说一句,你得到了一个NullReferenceException
,因为你错误地假设你的查询将始终返回一个节点。您现在可以看到当它不返回节点时会发生什么。每当查询可能不返回任何值时,请始终检查null
。
您可以使用 Linq to XML 的 XmlDocument 类,这很容易。您需要使用 System.Xml.Linq namspace,例如:
XDocument xdoc = XDocument.Load("path");
IEnumerable<XElement> nodes = (from p in xdoc.Descendants()
where p.Name.LocalName == "FirstName"
select p).Elements();
foreach (XElement nodeFirstName in nodes)
{
foreach (XElement parts in nodeFirstName.Elements())
{
string strExtracted = parts.Name.LocalName + " " + parts.Value;
}
}
使用 LocalName 属性是因为元素具有前缀"cdsd">