[英]Saxon extension: XPath on XdmNode
Hi I try to implement an extension for saxon in C#. 嗨,我尝试在C#中实现撒克逊的扩展。 I use the saxon9he interface. 我使用saxon9he界面。 The extension itself works fine but now I want to use XPath expressions to get values from a node. 扩展本身工作正常,但现在我想使用XPath表达式从节点获取值。 I break it down to the relevant code part (the rest is working fine). 我将其分解为相关的代码部分(其余的工作正常)。
The extension has two arguments. 扩展有两个参数。 The first one is a string, the second one is a node-set. 第一个是字符串,第二个是节点集。
public override IXdmEnumerator Call(IXdmEnumerator[] arguments, DynamicContext context)
{
if (arguments.Length == 2)
{
arguments[0].MoveNext();
string text = (arguments[0].Current as XdmAtomicValue).Value as string;
IXdmEnumerator enumerator = arguments[1];
while (enumerator.MoveNext())
{
XdmNode node = (XdmNode)enumerator.Current;
// how can I get values from node here by using XPath expressions?
// e.g. I want the value of the attribute "type" of the subnode "xy"
// XPath would be something like this: "./xy/@type"
text = text.Replace(node.NodeName.LocalName, node.StringValue);
}
var result = new XdmAtomicValue(text);
return (IXdmEnumerator)result.GetEnumerator();
}
...
}
The 3 comments in the middle show my problem. 中间的3条评论显示了我的问题。 I want to access subnodes, attributes and so on by XPath expressions. 我想通过XPath表达式访问子节点,属性等。 This is a simplified version. 这是一个简化版本。 The XPath should be passed as an additional argument later. 稍后应将XPath作为附加参数传递。 So it is not a fixed XPath expression that I could transform to code. 所以它不是一个固定的XPath表达式,我可以转换为代码。 I really need an XPath evaluator. 我真的需要一个XPath评估器。
I saw a solution by creating an XPathEvaluator from a Processor. 我通过从处理器创建XPathEvaluator看到了一个解决方案。 But I have no Processor at this point, or do I? 但是我现在没有处理器,或者我呢?
Thanks for help. 感谢帮助。
Here is the solution (thanks to Michael): 这是解决方案(感谢迈克尔):
var configuration = context.Implementation.getConfiguration();
var processor = (Processor)configuration.getProcessor();
var xpathCompiler = processor.NewXPathCompiler();
while (enumerator.MoveNext())
{
XdmNode node = (XdmNode)enumerator.Current;
var keyResult = xpathCompiler.Evaluate(searchXPath, node);
var valueResult = xpathCompiler.Evaluate(replaceXPath, node);
string key = "";
string value = "";
if (keyResult is XdmAtomicValue)
key = (string)(keyResult as XdmAtomicValue).Value;
else if (keyResult is XdmNode)
key = (string)(keyResult as XdmNode).StringValue;
if (valueResult is XdmAtomicValue)
value = (string)(valueResult as XdmAtomicValue).Value;
else if (valueResult is XdmNode)
value = (string)(valueResult as XdmNode).StringValue;
if (string.IsNullOrWhiteSpace(key) || value == null)
continue;
text = text.Replace(key, value);
}
Solution for Saxon 9.7: Saxon 9.7的解决方案:
The solution above doesn't work for Saxon 9.7 anymore. 上面的解决方案不再适用于Saxon 9.7。 In this case I pass the processor to the extension classes and from there to the extension call classes at the time I register the extensions. 在这种情况下,我将处理器传递给扩展类,并在注册扩展时从那里传递到扩展调用类。
public static void RegisterSaxonExtensions(Saxon.Api.Processor processor)
{
processor.RegisterExtensionFunction(new MyExtension1(processor));
processor.RegisterExtensionFunction(new MyExtension2(processor));
}
...
public class MyExtension1 : Saxon.Api.ExtensionFunctionDefinition
{
private Saxon.Api.Processor processor = null;
public MyExtension1(Saxon.Api.Processor processor)
{
this.processor = processor;
}
public override ExtensionFunctionCall MakeFunctionCall()
{
return new MyExtension1Call(this.processor);
}
...
}
public class MyExtension1Call : Saxon.Api.ExtensionFunctionCall
{
private Saxon.Api.Processor processor = null;
public MyExtension1Call(Saxon.Api.Processor processor)
{
this.processor = processor;
}
public override IXdmEnumerator Call(IXdmEnumerator[] arguments, DynamicContext context)
{
if (arguments.Length == 2)
{
arguments[0].MoveNext();
string text = (arguments[0].Current as XdmAtomicValue).Value as string;
IXdmEnumerator enumerator = arguments[1];
var xpathCompiler = this.processor.NewXPathCompiler();
while (enumerator.MoveNext())
{
XdmNode node = (XdmNode)enumerator.Current;
var keyResult = xpathCompiler.Evaluate(searchXPath, node);
var valueResult = xpathCompiler.Evaluate(replaceXPath, node);
string key = "";
string value = "";
if (keyResult is XdmAtomicValue)
key = (string)(keyResult as XdmAtomicValue).Value;
else if (keyResult is XdmNode)
key = (string)(keyResult as XdmNode).StringValue;
if (valueResult is XdmAtomicValue)
value = (string)(valueResult as XdmAtomicValue).Value;
else if (valueResult is XdmNode)
value = (string)(valueResult as XdmNode).StringValue;
if (string.IsNullOrWhiteSpace(key) || value == null)
continue;
text = text.Replace(key, value);
}
var result = new XdmAtomicValue(text);
return (IXdmEnumerator)result.GetEnumerator();
}
}
}
DynamicContext.Implementation gives you an XPathContext object, this has a getConfiguration() method to get to the Configuration, and the Processor object should be found in Configuration.getProcessor(). DynamicContext.Implementation为您提供了一个XPathContext对象,它有一个getConfiguration()方法来访问Configuration,而Processor对象应该在Configuration.getProcessor()中找到。 From that you should be able to create an XPathEvaluator. 从那以后你应该能够创建一个XPathEvaluator。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.