我正在try 以编程方式定位由XPath标识的XML文本中的元素.也就是说,不仅要在解析的XML struct 中找到引用的元素,还要确定原始XML文档中的开始和结束字符位置.

更多关于我试图解决的问题:我维护一个将XMLs发送到Web服务的C#程序.如果Web服务报告错误(在数据级别,而不是在XML语法中),则错误响应将错误的位置作为XPath包含.我想要做的是找到标识的元素,以便在UI中突出显示它.

我发现了XPathNavigator和XmlNode.SelectSingleNode,但它们似乎只在解析后的XML struct 上操作.如果有一种方法可以将这些映射回原始XML中的行/字符位置,我是看不到的.

有谁能帮忙吗?

精简后的示例:

<?xml version="1.0" encoding="utf-8"?>
<ODM xmlns="http://www.cdisc.org/ns/odm/v1.3" ODMVersion="1.3" FileType="Transactional">
  <ClinicalData StudyOID="xxx" MetaDataVersionOID="1">
    <SubjectData SubjectKey="yyy" TransactionType="Insert">
      <SiteRef LocationOID="zzz" />
    </SubjectData>
  </ClinicalData>
</ODM>

错误响应中的XPath如下所示:

/ODM/ClinicalData[1]/SubjectData[1]

推荐答案

XDocument允许使用某些选项进行解析以公开IXmlLineInfo:

var linqXmlDoc = XDocument.Load("sample1.xml", LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);

var linqNode = linqXmlDoc.XPathSelectElement(xpath);

if (linqNode is IXmlLineInfo linqLineInfo)
{
    Console.WriteLine("XNode.LineNumber {0}", linqLineInfo.LineNumber);
}

对于XPathDocument/XPathNavigator,我还会得到一个IXmlLineInfo:

var xpathDocument = new XPathDocument("sample1.xml");

var xpathNode = xpathDocument.CreateNavigator().SelectSingleNode(xpath);

if (xpathNode is IXmlLineInfo xpathLineInfo)
{
    Console.WriteLine("XPath LineInfo: {0}", xpathLineInfo.LineNumber);
}

至于您获得的XPath表达式的问题,在XPath 1.0的上下文中,该表达式使用在您的XML样例中声明的默认名称空间,不会 Select 任何东西.如果您可以使用例如NuGet包https://www.nuget.org/packages/XPath2迁移到XPath 2,那么您可以使用(使用using Wmhelp.XPath2;)例如

var xmlNsMgr = new XmlNamespaceManager(new NameTable());

xmlNsMgr.AddNamespace("", "http://www.cdisc.org/ns/odm/v1.3");

var linqNode = linqXmlDoc.XPath2SelectElement(xpath, xmlNsMgr);

带有一个具有默认名称空间声明并显示XmlNamespaceManagerXPath2SelectSingleNodeXPath2SelectElement的用法的样例XML文档的完整样例项目位于https://github.com/martin-honnen/XPath2DefaultElementNSExample2.

Csharp相关问答推荐

在C# 11之前, struct 中的每个字段都必须显式分配?不能繁殖

Blazor:计算值或保留为默认值

如何在Visual Studio中为C# spread操作符设置格式规则?

Blazor:类型或命名空间名称Components在命名空间中不存在''

System. InvalidOperationException:无法将数据库中的字符串值i转换为映射的ItemType枚举中的任何值''''

"virtual"修饰符对接口成员有什么影响?

为什么C#Bigbit不总是相同的比特长度?

如何修改中间件或其注册以正确使用作用域服务?

如何在C#中将对象[*,*]直接转换为字符串[*,*]?

如何在C#中从正则表达式中匹配一些数字但排除一些常量(也是数字)

实体框架核心中的ComplexType和OwnsOne有什么不同?

反序列化私有成员

N层解决方案上的依赖注入-删除样板

CA1508:';NULL=>;TRUE;始终为';TRUE';.移除或重构条件(S)以避免死代码

交替的奇数

无法使用[FromForm]发送带有图像和JSON的多部分请求

如何在Akka.NET中重新启动执行元时清除邮箱

如何在C#中正确类型化带有泛型的嵌套类

如何在使用Google.Drive.apis.V3下载文件/文件夹之前压缩?

如何使用IHostedService添加数据种子方法