Saxonica - .NET API - XQuery - XPDY0002: 轴步骤rootdescendant::xxx的上下文项不存在。

问题描述 投票:0回答:1

SaxonApiException: 轴步骤.CLIENT的上下文项不存在。

当从命令行运行时,一切正常。 所以我不认为XQuery本身存在语法问题。 除非需要,我不会把输入文件贴出来。

在错误出现之前,XQuery是用Console.WriteLine显示的。

----- Start: XQUERY:
(:  FLWOR = For Let Where Order-by Return   :)
<MyFlightLegs>
{
for $flightLeg in //FlightLeg
where $flightLeg/DepartureAirport = 'OKC' or $flightLeg/ArrivalAirport = 'OKC'
order by $flightLeg/ArrivalDate[1] descending
return $flightLeg
}
</MyFlightLegs>

----- End  : XQUERY:
Error evaluating (<MyFlightLegs {for $flightLeg in root/descendant::FlightLeg[DepartureAirport = "OKC" or ArrivalAirport = "OKC"] ... return $flightLeg}/>) on line 4 column 20
  XPDY0002: The context item for axis step root/descendant::FlightLeg is absent

我想和其他问题一样,可能是我的输入XML文件没有正确指定。

我把XQuerytoStream类的samplescsExamplesHE.cs运行方法。

为了方便参考,那里的代码是。

public class XQueryToStream : Example
{

    public override string testName
    {
        get { return "XQueryToStream"; }
    }

    public override void run(Uri samplesDir)
    {
        Processor processor = new Processor();
        XQueryCompiler compiler = processor.NewXQueryCompiler();
        compiler.BaseUri = samplesDir.ToString();
        compiler.DeclareNamespace("saxon", "http://saxon.sf.net/");
        XQueryExecutable exp = compiler.Compile("<saxon:example>{static-base-uri()}</saxon:example>");
        XQueryEvaluator eval = exp.Load();
        Serializer qout = processor.NewSerializer();
        qout.SetOutputProperty(Serializer.METHOD, "xml");
        qout.SetOutputProperty(Serializer.INDENT, "yes");
        qout.SetOutputStream(new FileStream("testoutput.xml", FileMode.Create, FileAccess.Write));
        Console.WriteLine("Output written to testoutput.xml");
        eval.Run(qout);
    }

}

我把Xquery文件名、xml文件名和输出文件名都改成了传递,并试图用它来做一个静态方法。(用XSLT处理器做同样的事情成功了)。

static void DemoXQuery(string xmlInputFilename, string xqueryInputFilename, string outFilename)
{

    // Create a Processor instance.
    Processor processor = new Processor();

    // Load the source document
    DocumentBuilder loader = processor.NewDocumentBuilder();
    loader.BaseUri = new Uri(xmlInputFilename);
    XdmNode indoc = loader.Build(loader.BaseUri);

    XQueryCompiler compiler = processor.NewXQueryCompiler();
    //BaseUri is inconsistent with Transform= Processor? 
    //compiler.BaseUri = new Uri(xqueryInputFilename);
    //compiler.DeclareNamespace("saxon", "http://saxon.sf.net/");

    string xqueryFileContents = File.ReadAllText(xqueryInputFilename);
    Console.WriteLine("----- Start: XQUERY:");
    Console.WriteLine(xqueryFileContents);
    Console.WriteLine("----- End  : XQUERY:");
    XQueryExecutable exp = compiler.Compile(xqueryFileContents);
    XQueryEvaluator eval = exp.Load(); 

    Serializer qout = processor.NewSerializer();
    qout.SetOutputProperty(Serializer.METHOD, "xml");
    qout.SetOutputProperty(Serializer.INDENT, "yes");
    qout.SetOutputStream(new FileStream(outFilename, 
                 FileMode.Create, FileAccess.Write));

    eval.Run(qout);

}

还有两个关于 "BaseURI "的问题。1. 它应该是一个目录名,还是可以和Xquery文件名一样? 2.我得到这个编译错误。"Cannot implicity convert to "System.Uri" to "String".

compiler.BaseUri = new Uri(xqueryInputFilename);

这和我在XSLT上做的完全一样,成功了。但是看起来BaseUri对于XQuery来说是一个字符串,但是对于XSLT来说是一个真正的Uri对象? 有什么不同的原因吗?

saxon
1个回答
1
投票

你似乎问了一大堆独立的问题,很难分清。

你的C#代码似乎是在编译查询。

<saxon:example>{static-base-uri()}</saxon:example>

它与您提供的XQuery代码没有任何关系,涉及的是 MyFlightLegs.

MyFlightLegs 查询使用 //FlightLeg 并且显然是为了针对包含有一个 FlightLeg 元素,但你的C#代码并没有尝试提供这样一个文档。你需要添加一个 eval.ContextItem = value 语句。

您的第二个C#片段在以下行中创建了一个输入文档。

XdmNode indoc = loader.Build(loader.BaseUri);

但它并没有把它提供给查询评估器。

基础URI可以是一个目录或文件;解析了 relative.xml 与...对抗 file:///my/dir/ 的结果与对其进行解析的结果完全相同。file:///my/dir/query.xq. 但按照惯例,查询的静态基础URI是包含源查询文本的资源(如文件)的URI。

是的,在API设计中,字符串与URI对象的使用有很多不一致的地方。(也有不一致的关于 BaseURI 与...相比 BaseUri.) 很抱歉,你只能忍受它了。


0
投票

基于Michael Kay的响应的底线解决方案;我在做完exp.Load()后添加了这行代码。

eval.ContextItem = indoc;

之前创建的indoc对象是与XQuery处理的XML输入文件相关的。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.