C#.Net对象序列化为XmlDocument后GetElementById返回null求助
解决XmlDocument.GetElementById返回null的问题
这个问题我之前也碰到过!原因是GetElementById的工作机制和你想的不太一样——它默认只识别两种属性:
- 无命名空间的小写
id属性 - 在XML Schema(XSD)或DTD中被定义为
ID类型的属性
而你序列化出来的Id属性属于http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd命名空间(前缀p3),默认不会被XmlDocument标记为ID属性,所以内部的_htElementIdMap里没有对应的条目,调用GetElementById自然返回null。
下面给你几个可行的解决方案:
方案1:用XPath手动查找(最直接)
既然知道目标属性的命名空间和值,可以用SelectSingleNode配合XPath精准定位:
// 方法1:通过命名空间URI和属性名查找 var result1 = timestampXmlElement.OwnerDocument.SelectSingleNode( "//*[@*[local-name()='Id' and namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd']='Test1']"); // 方法2:注册命名空间前缀后简化XPath XmlNamespaceManager nsMgr = new XmlNamespaceManager(timestampXmlElement.OwnerDocument.NameTable); nsMgr.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); var result2 = timestampXmlElement.OwnerDocument.SelectSingleNode("//*[@wsu:Id='Test1']", nsMgr);
方案2:把wsu:Id标记为ID类型,让GetElementById生效
如果你一定要用GetElementById,可以手动将目标属性的Schema类型设置为ID,这样XmlDocument就会把它加入到内部的ID映射表中:
// 获取带命名空间的Id属性 XmlAttribute idAttr = timestampXmlElement.Attributes["Id", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"]; if (idAttr != null) { // 将属性标记为ID类型 idAttr.SchemaType = XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.Id); } // 现在调用GetElementById就能得到结果了 var result3 = timestampXmlElement.OwnerDocument.GetElementById("Test1");
方案3:序列化时关联XmlSchema(适合批量场景)
如果你的类是基于WSS规范生成的,可以确保对应的XSD中Id属性被定义为ID类型,然后在序列化前将该XSD加载到XmlDocument的Schema集合中。不过这个方法相对复杂,适合需要大量处理这类XML的场景。
内容的提问来源于stack exchange,提问作者pieterVdM
相关产品推荐
相关产品推荐

