2017-02-10 10 views
1

안녕하세요 저는 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(); 
     } 
    } 
} 

답변

0

DynamicContext.Implementation이이 구성에 도착하기 위하여는, getConfiguration() 메소드를 가지고, 당신에게 XPathContext 객체를 제공하고, 프로세서 객체가 Configuration.getProcessor에서 발견되어야한다(). XPathEvaluator를 만들 수 있어야합니다.

+0

대단히 감사합니다. :) 이제 작동 중입니다. –

+0

안녕 마이클. 나는 작센 9.5에서 9.7로 바꿨다. 이제'configuration.getProcessor()'가'Saxon.Api.Processor' 대신'net.sf.saxon.s9api.Processor'를 반환하기 때문에 코드가 실패합니다. 나는 인터페이스가 비슷하다고 생각하지만'Saxon.Api' 네임 스페이스의 클래스를 어떻게 든 사용할 수 있습니까? 아니면'net.sf.saxon.s9api' 네임 스페이스의 코드를 사용하도록 코드를 조정해야합니까? –

+0

후자의 경우 :''Saxon.Api.XdmNode'를'net.sf.saxon.s9api.XPathCompiler.evaluate' 메소드가 필요로하는'net.sf.saxon.s9api.XdmItem'으로 어떻게 변환 할 수 있습니까? 입력으로? 그리고'evaluate' 메소드 ('net.sf.saxon.s9api.XdmValue')의 결과를'Saxon.Api.XdmValue'로 어떻게 변환 할 수 있습니까? –