Xpath 在有命名空间的 xml 文件中使用属性作为变量
Xpath using an attribute as a variable in an xml file where there is a namespace
如果我们有这个 xml 文件并且我想使用作者属性作为变量来获取标题
<bookstore>
<book author="Tommy">
<title>Emma</title>
</book>
</bookstore>
我知道我必须写这个
string au = "Tommy";
string query = String.Format("//bookstore/book[@author={0}]/title", au);
如果我们也有这个例子,我想获取标题
<bk:bookstore xmlns:bk="http://www.example.com/">
<book author="Tommy">
<title>Emma</title>
</book>
</bk:bookstore>
我知道我必须写这个
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("bk", "http://www.test.com/");
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book/title", nsmgr);
但是如果我有第二个例子,我不知道该怎么办,我也想使用属性Author作为变量。我试过这个
string au = "Tommy";
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("bk", "http://www.test.com/");
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book[@author={0}]/title", au, nsmgr);
或这个
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book[@author={0}]/title", nsmgr, au);
或这个
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book[@author={1}]/title", nsmgr, au);
但它不起作用。
有人可以帮我吗?
你把事情搞混了。
首先构建路径。然后使用它。命名空间管理器仅对第二步重要。
string au = "Tommy";
string path = String.Format("//bk:bookstore/book[@author = '{0}']/title", au);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("bk", "http://www.test.com/");
XmlNodeList elements0 = xml.SelectNodes(path, nsmgr);
注意路径中的单引号。
另请注意,当输入字符串 (au
) 中存在单引号时,此 将 中断。在最好的情况下,这可能是随机 运行 时间错误的来源,在最坏的情况下,这可能是 XPath 注入的攻击向量。这意味着您必须处理这种情况。
解决此问题的选项是:
- 明确禁止在输入中使用单引号,并在构建路径时另外使用
au.Replace("'", "")
。这可能不适合人名。
- 建立一个允许单引号的更复杂的路径。这不是微不足道的,因为 XPath 没有字符串转义机制。
- Use a more advanced way of defining an XPath query.
对于选项 2,假设作者 "O'Reilly"
,路径需要如下所示:
//bk:bookstore/book[@author = concat('O', "'", 'Reilly')]/title
因为表达式 concat('O', "'", 'Reilly')
在 XPath 引擎中生成字符串 "O'Reilly"
。以这种方式使用 concat()
是将定界引号嵌入 XPath 字符串的唯一方法。
这个函数产生这样一个表达式:
public static string XPathEscape(string input)
{
if (String.IsNullOrEmpty(input)) return "''";
if (input.Contains("'"))
{
string[] parts = input.Split("'".ToCharArray());
return String.Format("concat('{0}')", String.Join(@"', ""'"", '", parts));
}
else
{
return String.Format("'{0}'", input);
}
}
使用方法如下:
string au = "O'Reilly";
string path = String.Format("//bk:bookstore/book[@author = {0}]/title", XPathEscape(au));
注意这次路径中没有单引号。
如果我们有这个 xml 文件并且我想使用作者属性作为变量来获取标题
<bookstore>
<book author="Tommy">
<title>Emma</title>
</book>
</bookstore>
我知道我必须写这个
string au = "Tommy";
string query = String.Format("//bookstore/book[@author={0}]/title", au);
如果我们也有这个例子,我想获取标题
<bk:bookstore xmlns:bk="http://www.example.com/">
<book author="Tommy">
<title>Emma</title>
</book>
</bk:bookstore>
我知道我必须写这个
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("bk", "http://www.test.com/");
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book/title", nsmgr);
但是如果我有第二个例子,我不知道该怎么办,我也想使用属性Author作为变量。我试过这个
string au = "Tommy";
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("bk", "http://www.test.com/");
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book[@author={0}]/title", au, nsmgr);
或这个
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book[@author={0}]/title", nsmgr, au);
或这个
XmlNodeList elements0 = xml.SelectNodes("//bk:bookstore/book[@author={1}]/title", nsmgr, au);
但它不起作用。 有人可以帮我吗?
你把事情搞混了。
首先构建路径。然后使用它。命名空间管理器仅对第二步重要。
string au = "Tommy";
string path = String.Format("//bk:bookstore/book[@author = '{0}']/title", au);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("bk", "http://www.test.com/");
XmlNodeList elements0 = xml.SelectNodes(path, nsmgr);
注意路径中的单引号。
另请注意,当输入字符串 (au
) 中存在单引号时,此 将 中断。在最好的情况下,这可能是随机 运行 时间错误的来源,在最坏的情况下,这可能是 XPath 注入的攻击向量。这意味着您必须处理这种情况。
解决此问题的选项是:
- 明确禁止在输入中使用单引号,并在构建路径时另外使用
au.Replace("'", "")
。这可能不适合人名。 - 建立一个允许单引号的更复杂的路径。这不是微不足道的,因为 XPath 没有字符串转义机制。
- Use a more advanced way of defining an XPath query.
对于选项 2,假设作者 "O'Reilly"
,路径需要如下所示:
//bk:bookstore/book[@author = concat('O', "'", 'Reilly')]/title
因为表达式 concat('O', "'", 'Reilly')
在 XPath 引擎中生成字符串 "O'Reilly"
。以这种方式使用 concat()
是将定界引号嵌入 XPath 字符串的唯一方法。
这个函数产生这样一个表达式:
public static string XPathEscape(string input)
{
if (String.IsNullOrEmpty(input)) return "''";
if (input.Contains("'"))
{
string[] parts = input.Split("'".ToCharArray());
return String.Format("concat('{0}')", String.Join(@"', ""'"", '", parts));
}
else
{
return String.Format("'{0}'", input);
}
}
使用方法如下:
string au = "O'Reilly";
string path = String.Format("//bk:bookstore/book[@author = {0}]/title", XPathEscape(au));
注意这次路径中没有单引号。