正如 Michael Kay 所说,这里的正确方法是使用 XPath 变量,但是使用内置的 .NET API 有点棘手。我将在下面提供一个(非常简单的)类示例,该类允许您定义 XPath 变量。一旦你有了它,你可以像这样使用它:
VariableContext context =
new VariableContext { { "hello", 4 }, { "goodbye", "adios" } };
// node is a System.Xml.XmlNode object
XmlNodeList result =
node.SelectNodes("/my/field[. = $hello or . = $goodbye]", context);
同样的类也应该与XmlNode.SelectSingleNode()
、XPathNavigator.Select()
、XPathNavigator.SelectSingleNode()
、XPathNavigator.Evaluate()
和XElement
.
这提供了一种将用户提供的数据值合并到 XPath 中的安全方法,但与 Tomalak 的回答一样,它没有解决如何允许用户提供整个 XPath 的问题。我认为没有一种方法可以确定 XPath 的一部分是否客观安全,因此如果您担心这会带来安全风险,那么唯一的解决方案就是不这样做。
这是课程。如果您想让它处理名称空间和类似的东西,则需要添加。
class VariableContext : XsltContext
{
private Dictionary<string, object> m_values;
public VariableContext()
{
m_values = new Dictionary<string, object>();
}
public void Add(string name, object value)
{
m_values[name] = value;
}
public override IXsltContextVariable ResolveVariable(string prefix, string name)
{
return new XPathVariable(m_values[name]);
}
public override int CompareDocument(string baseUri, string nextbaseUri)
{
throw new NotImplementedException();
}
public override bool PreserveWhitespace(XPathNavigator node)
{
throw new NotImplementedException();
}
public override IXsltContextFunction ResolveFunction(string prefix, string name,
XPathResultType[] ArgTypes)
{
throw new NotImplementedException();
}
public override bool Whitespace
{
get { throw new NotImplementedException(); }
}
private class XPathVariable : IXsltContextVariable
{
private object m_value;
internal XPathVariable(object value)
{
m_value = value;
}
public object Evaluate(XsltContext xsltContext)
{
return m_value;
}
public bool IsLocal
{
get { throw new NotImplementedException(); }
}
public bool IsParam
{
get { throw new NotImplementedException(); }
}
public XPathResultType VariableType
{
get { throw new NotImplementedException(); }
}
}
}