編集:コメントで以下に説明することを達成するために私が見ることができる唯一の方法は、LINQ to XML、XPath変数を使用するか、独自のcurrent()
関数を定義することです。XPath変数と現在の関数は、それらを処理するために独自のクラスを作成する必要があるため、少し面倒ですが、これらの比較的単純なジェネリッククラスを使用できます。
public class VariableContext : XsltContext
{
IXPathNavigable CurrentNode;
Dictionary<string, object> Values = new Dictionary<string, object>();
public void SetValue(string name, object value)
{
Values[name] = value;
}
public void SetCurrentNode(IXPathNavigable currentNode)
{
CurrentNode = currentNode;
}
public override int CompareDocument(string baseUri, string nextbaseUri)
{
throw new NotImplementedException();
}
public override bool PreserveWhitespace(System.Xml.XPath.XPathNavigator node)
{
return false;
}
public override IXsltContextFunction ResolveFunction(string prefix, string name, System.Xml.XPath.XPathResultType[] ArgTypes)
{
if (name.Equals("current"))
{
return new CurrentFunction(CurrentNode);
}
throw new NotImplementedException();
}
public override IXsltContextVariable ResolveVariable(string prefix, string name)
{
object value;
if (Values.TryGetValue(name, out value))
{
return new ContextVariable(name, value);
}
throw new ApplicationException("Unknown variable: " + name);
}
public override bool Whitespace
{
get { return false; }
}
}
public class ContextVariable : IXsltContextVariable
{
private string m_name;
private object m_parameter;
public ContextVariable(string name, object parameter)
{
m_name = name;
m_parameter = parameter;
IXPathNavigable navigable = m_parameter as IXPathNavigable;
if (navigable != null)
{
m_parameter = navigable.CreateNavigator().Select(".");
}
}
#region IXsltContextVariable Members
public object Evaluate(XsltContext xsltContext)
{
return m_parameter;
}
public bool IsLocal
{
get { return true; }
}
public bool IsParam
{
get { return true; }
}
public XPathResultType VariableType
{
get
{
return XPathResultType.Any;
}
}
#endregion
}
public class CurrentFunction : IXsltContextFunction
{
private XPathNodeIterator CurrentNodeIterator;
internal CurrentFunction(IXPathNavigable currentNode)
{
if (currentNode != null)
{
CurrentNodeIterator = currentNode.CreateNavigator().Select(".");
}
}
public XPathResultType[] ArgTypes
{
get { return new XPathResultType[0]; }
}
public object Invoke(XsltContext xsltContext, object[] args,
XPathNavigator docContext)
{
if (CurrentNodeIterator == null)
{
throw new ApplicationException("Current node is not set.");
}
return CurrentNodeIterator;
}
public int Maxargs
{
get { return 0; }
}
public int Minargs
{
get { return 0; }
}
public XPathResultType ReturnType
{
get { return XPathResultType.NodeSet; }
}
}
どこかでそれを定義したら、次のことができます。
VariableContext vc = new VariableContext();
XmlNode nodea = doc.SelectSingleNode("Root/Start[1]");
vc.SetValue("a", nodea);
XmlNodeList selected = doc.SelectNodes("/Root/Item[@id = $a/@refId]", vc);
または、カスタム定義のcurrent()
関数を使用します。
VariableContext vc2 = new VariableContext();
XmlNode nodea2 = doc.SelectSingleNode("Root/Start[1]");
vc2.SetCurrentNode(nodea2);
XmlNodeList selected2 = doc.SelectNodes("/Root/Item[@id = current()/@refId]", vc2);
PrintNodeList(selected2);
ワーキングイデオネ:http://ideone.com/7wsQ46