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对象? 有什么不同的原因吗?
你似乎问了一大堆独立的问题,很难分清。
你的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
.) 很抱歉,你只能忍受它了。
基于Michael Kay的响应的底线解决方案;我在做完exp.Load()后添加了这行代码。
eval.ContextItem = indoc;
之前创建的indoc对象是与XQuery处理的XML输入文件相关的。