2017-02-10 94 views
1

您好我嘗試在C#中實現撒克遜擴展。我使用saxon9he界面。擴展本身工作正常,但現在我想使用XPath表達式從節點獲取值。我把它分解到相關的代碼部分(其餘的工作正常)。撒克遜擴展:XdmNode上的XPath

擴展名有兩個參數。第一個是字符串,第二個是節點集。

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。但是我現在沒有處理器,或者我呢?

感謝您的幫助。

這裏是解決方案(感謝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); 
} 

解決方案撒克遜9.7:

上述解決方案不適用於撒克遜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給你一個XPathContext對象,這有getConfiguration()方法來獲得的配置,處理器對象應在Configuration.getProcessor找到()。從那你應該可以創建一個XPathEvaluator。

+0

非常感謝! :)現在它工作。 –

+0

嗨邁克爾。我從撒克遜HE 9.5切換到HE 9.7。現在我的代碼失敗了,因爲'configuration.getProcessor()'現在返回一個'net.sf.saxon.s9api.Processor'而不是'Saxon.Api.Processor'。我猜接口是相似的,但是我可以用'Saxon.Api'命名空間的類來處理嗎?還是應該調整代碼以使用'net.sf.saxon.s9api'命名空間中的代碼? –

+0

如果後者是這種情況:如何將'Saxon.Api.XdmNode'轉換爲'net.sf.saxon.s9api.XdmItem',其中'net.sf.saxon.s9api.XPathCompiler.evaluate'方法需要作爲輸入?我怎樣才能將'evaluate'方法('net.sf.saxon.s9api.XdmValue')的結果轉換回'Saxon.Api.XdmValue'? –