调用XPathSelectElement()传入属性XPath时抛出System.InvalidOperationException异常
问题根源
XPathSelectElement方法仅能返回XML元素节点(XElement),而你使用的XPath /track/@name 匹配的是属性节点(XAttribute),类型不匹配导致抛出System.InvalidOperationException异常。
解决方案
提供三种可行的解决思路:
方案一:修改方法支持任意节点类型
将方法返回类型改为XObject(XElement和XAttribute的基类),使用XPathEvaluate替代XPathSelectElement,支持获取元素或属性:
public static XObject GetXPathNode(XElement element, string xpathKey) { try { if (xPathKeys.TryGetValue(xpathKey, out string xpath)) { var result = element.XPathEvaluate(xpath); // 处理XPath返回的单个节点或节点集合 if (result is IEnumerable enumerable) { return enumerable.Cast<XObject>().FirstOrDefault(); } return result as XObject; } else { LOG.Log.Logfunction?.Invoke((int)EATSLogLevels.Error, $"Key or value not found. Key: {xpathKey}"); return null; } } catch (Exception ex) { // 修复原catch块中可能的KeyNotFoundException string targetXPath = xPathKeys.TryGetValue(xpathKey, out var x) ? x : "unknown"; LOG.Log.Logfunction?.Invoke((int)EATSLogLevels.Error, $"XPath execution failed. Key: {xpathKey}, XPath: {targetXPath} " + ex.Message); return null; } }
调用时判断节点类型:
var node = GetXPathNode(yourTrackElement, "yourXPathKey"); if (node is XAttribute nameAttr) { string nameValue = nameAttr.Value; // 得到"A1" } else if (node is XElement elem) { // 处理元素逻辑 }
方案二:先获取元素再单独取属性
不修改现有GetXElement方法,调整XPath为/track(匹配元素节点),获取到XElement后再通过Attribute方法取属性:
var trackElem = GetXElement(yourRootElement, "trackKey"); // 对应XPath为"/track" if (trackElem != null) { XAttribute nameAttr = trackElem.Attribute("name"); string nameValue = nameAttr?.Value; }
方案三:新增专门的属性获取方法
如果需要保留原GetXElement方法的功能,新增一个专门获取属性的方法:
public static XAttribute GetXAttribute(XElement element, string xpathKey) { try { if (xPathKeys.TryGetValue(xpathKey, out string xpath)) { var result = element.XPathEvaluate(xpath); return result as XAttribute ?? (result is IEnumerable enumerable ? enumerable.Cast<XAttribute>().FirstOrDefault() : null); } else { LOG.Log.Logfunction?.Invoke((int)EATSLogLevels.Error, $"Key or value not found. Key: {xpathKey}"); return null; } } catch (Exception ex) { string targetXPath = xPathKeys.TryGetValue(xpathKey, out var x) ? x : "unknown"; LOG.Log.Logfunction?.Invoke((int)EATSLogLevels.Error, $"XPath execution failed. Key: {xpathKey}, XPath: {targetXPath} " + ex.Message); return null; } }
调用时直接使用该方法,XPath保持/track/@name即可:
var nameAttr = GetXAttribute(yourRootElement, "nameAttrKey"); string nameValue = nameAttr?.Value;
额外注意
原方法的catch块中直接使用xPathKeys[xpathKey]存在风险:如果xpathKey不存在于字典中,会触发KeyNotFoundException,建议改用上述代码中的方式,先尝试取值再处理。
内容的提问来源于stack exchange,提问作者Arun K
相关产品推荐
相关产品推荐

