如何在 C# 中使用 XPath 包含
Posted
技术标签:
【中文标题】如何在 C# 中使用 XPath 包含【英文标题】:How to use XPath contains in C# 【发布时间】:2021-04-05 14:49:35 【问题描述】:我正在努力使用 XPATH 中的 contains(text,'some text')。
我看到了这个链接How to use XPath contains(),但由于某种原因对我不起作用
我需要删除项目引用,因此我只想使用“ProjectName”进行选择(不指定完整路径) 我从这个答案How do I use Powershell to add/remove references to a csproj? 中获取了一个脚本(请参阅 RemoveReference.ps1)
这是我的代码,也是一个小提琴https://dotnetfiddle.net/Cq5fa6
using System;
using System.Xml;
public class Program
public static void Main()
//Declare the XML Document here
XmlDocument Doc = new XmlDocument();
//Load you xml here
//Doc.LoadXml(TransportResponse.Response)
Doc.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
<Project ToolsVersion=""15.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
<ItemGroup>
<ProjectReference Include=""..\ProjectReferencesToolkit.Core\ProjectReferencesToolkit.Core.csproj"">
<Project>6c167ddd-7ce8-4087-9f8c-6986145b97d1</Project>
<Name>ProjectReferencesToolkit.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />
</Project>
");
//I need to use contains here to only search for ProjectReferencesToolkit.Core.csproj (not specifying full path)
var XPath = String.Format("//a:ProjectReference[@Include='0']","..\\ProjectReferencesToolkit.Core\\ProjectReferencesToolkit.Core.csproj");
var nsmgr = new XmlNamespaceManager(Doc.NameTable);
nsmgr.AddNamespace("a","http://schemas.microsoft.com/developer/msbuild/2003");
var node = Doc.SelectSingleNode(XPath, nsmgr);
Console.WriteLine(node.InnerXml);
【问题讨论】:
你知道,一般来说我会说这是一个坏主意......你如何将字符串转义为 xpath 字符串?假设文件名是My'Beautiful'Flower.csproj
...
我没有那种 csproj 文件名。
如果你不在你的项目或文件夹中尝试一些有趣的名字,你作为程序员的生活一定很无聊:-) :-) 如果你不破坏资源管理器,你就是' t 甚至玩 :-)
【参考方案1】:
我认为这是个坏主意。在 XPath 中转义字符串很痛苦。
我正在做一个ends-with
而不是contains
,这应该更适合你想要的。明明ends-with
是XPath 2.0,.NET只支持1.0,所以只好用substring
。
string fileName = "ProjectReferencesToolkit.Core.csproj";
var XPath = string.Format("//a:ProjectReference[substring(@Include, string-length(@Include) - 0 + 1) = '1']", fileName.Length, fileName);
还有一点转义:
// https://***.com/a/38254661/613130
public static string EscapeXPathString(string value)
if (!value.Contains("'"))
return '\'' + value + '\'';
else if (!value.Contains("\""))
return '"' + value + '"';
else
return "concat('" + value.Replace("'", "',\"'\",'") + "')";
在xml中:
<ProjectReference Include=""..\ProjectReferencesToolkit.Core\ProjectReferencesToolkit"'.Core.csproj"">
然后:
string fileName = @"ProjectReferencesToolkit""'.Core.csproj";
string fileNameEscaped = EscapeXPathString(fileName);
var XPath = string.Format("//a:ProjectReference[substring(@Include, string-length(@Include) - 0 + 1) = 1]", fileName.Length, fileNameEscaped);
(现在我已经摆脱了 XPath 字符串,我感觉好多了?)
【讨论】:
谢谢,我试试看告诉你【参考方案2】:最好使用 LINQ to XML API。它自 2007 年起在 .Net Framework 中可用。
c#
void Main()
XDocument xsdoc = XDocument.Parse(@"<?xml version='1.0' encoding='utf-8'?>
<Project ToolsVersion='15.0'
xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
<ItemGroup>
<ProjectReference Include='..\ProjectReferencesToolkit.Core\ProjectReferencesToolkit.Core.csproj'>
<Project>6c167ddd-7ce8-4087-9f8c-6986145b97d1</Project>
<Name>ProjectReferencesToolkit.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets'/>
</Project>");
string SearchFor = @"ProjectReferencesToolkit.Core.csproj";
XNamespace ns = xsdoc.Root.GetDefaultNamespace();
XElement xelem = xsdoc.Descendants(ns + "ProjectReference")
.FirstOrDefault(x => x.Attribute("Include").Value.EndsWith(SearchFor));
Console.WriteLine(xelem);
【讨论】:
以上是关于如何在 C# 中使用 XPath 包含的主要内容,如果未能解决你的问题,请参考以下文章
如何使用多个 XPath 查询在 c# 中选择单个 XML 节点
如何在 PHP 中使用 XPath 设置 (not(contains))