안녕하세요 저는 C#에서 saxon 용 확장 프로그램을 구현하려고합니다. 나는 saxon9he 인터페이스를 사용합니다. 확장 자체가 잘 작동하지만 이제 XPath 표현식을 사용하여 노드에서 값을 가져 오려고합니다. 관련 코드 부분 (나머지는 정상적으로 작동 함)으로 나눕니다.Saxon 확장 : XPath on XdmNode
확장 프로그램에는 두 개의 인수가 있습니다. 첫 번째는 문자열이고 두 번째는 노드 집합입니다.
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();
}
...
}
중간에 3 개의 댓글이 내 문제를 보여줍니다. XPath 식으로 하위 노드, 속성 등에 액세스하려고합니다. 이것은 단순화 된 버전입니다. 나중에 XPath를 추가 인수로 전달해야합니다. 따라서 코드로 변환 할 수있는 고정 된 XPath식이 아닙니다. 정말 XPath 평가 기가 필요합니다.
프로세서에서 XPathEvaluator를 만들어 솔루션을 보았습니다. 하지만이 시점에서 프로세서가 없습니까?
도움 주셔서 감사합니다. 색슨 9.7
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);
}
솔루션 :이 솔루션은 위의 더 이상 색슨 9.7이 작동하지 않습니다
여기
은 (마이클 덕분에) 솔루션입니다. 이 경우 프로세서를 확장 클래스에 전달하고 확장 클래스를 등록 할 때 확장 호출 클래스로 전달합니다.
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();
}
}
}
대단히 감사합니다. :) 이제 작동 중입니다. –
안녕 마이클. 나는 작센 9.5에서 9.7로 바꿨다. 이제'configuration.getProcessor()'가'Saxon.Api.Processor' 대신'net.sf.saxon.s9api.Processor'를 반환하기 때문에 코드가 실패합니다. 나는 인터페이스가 비슷하다고 생각하지만'Saxon.Api' 네임 스페이스의 클래스를 어떻게 든 사용할 수 있습니까? 아니면'net.sf.saxon.s9api' 네임 스페이스의 코드를 사용하도록 코드를 조정해야합니까? –
후자의 경우 :''Saxon.Api.XdmNode'를'net.sf.saxon.s9api.XPathCompiler.evaluate' 메소드가 필요로하는'net.sf.saxon.s9api.XdmItem'으로 어떻게 변환 할 수 있습니까? 입력으로? 그리고'evaluate' 메소드 ('net.sf.saxon.s9api.XdmValue')의 결과를'Saxon.Api.XdmValue'로 어떻게 변환 할 수 있습니까? –