XPath 3.0 in C# with Saxonica API

Today, I was playing with using Saxonica’s .NET API in C# (Microsoft .NET).

The program below was based on the sample here:
c:\Saxonica\Resources\samples\cs\ExamplesHE.cs
You can download the samples from Saxonica on SourceForge in the file that starts with “Resources”.

Sample C# Program

<pre>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//Do an "Add Reference" to C:\Saxonica\bin\saxon9he-api.dll (where you stored it on your disk)
using Saxon.Api;   //use this, not SaxonAPI - as Saxon.Api contains the "Processor" Class 

namespace SaxonAPI
{
    class Program
    {
        static void Main(string[] args)
        {
            string filename = @"c:\XMLClass\IntroSamples\Flight03.xml";

            // First two examples show how to return a single value, and them multiple values. 
            string xpath1 = "/Reservation/Flight[1]/FlightLeg[1]/FlightNumber/text()";
            string xpath2 = "/Reservation/Flight/FlightLeg/FlightNumber";

            // The third example shows use of XPath 3.0 features, such as the || concatenation operator 
            string xpath3 = "/Reservation/AirlineIATACode || '-' || /Reservation/Flight[1]/FlightLeg[1]/FlightNumber";

            // Call the test methods 
            string resultFlightNumber = DemoXPathSingle(filename, xpath1);
            string resultFlightNumbers = DemoXPathMultiple(filename, xpath2);
            string resultXpath30 = DemoXPathSingle(filename, xpath3);

            Console.WriteLine("result FlightNumber=" + resultFlightNumber);
            Console.WriteLine("result FlightNumbers=" + resultFlightNumbers);
            Console.WriteLine("result XPath 3.0=" + resultXpath30);

            Console.WriteLine("\n\nPress enter to end:");
            Console.ReadLine(); 
        }

        static string  DemoXPathSingle(string parmFilename, string parmXPath)
        {
            
            // Create a Processor instance.
            Processor processor = new Processor();

            // Load the source document
            //XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(parmFilename));

            // Create an XPath compiler
            XPathCompiler xpathCompiler = processor.NewXPathCompiler();

            // Enable caching, so each expression is only compiled once
            xpathCompiler.Caching = true;

            string result = "";

            result = xpathCompiler.EvaluateSingle(parmXPath, input).ToString();
            return result; 

            /*

            // Compile and evaluate some XPath expressions
            foreach (XdmItem item in xpathCompiler.Evaluate(parmXPath, input))
            {

                Console.WriteLine("TITLE: " + xpathCompiler.EvaluateSingle("string(TITLE)", item));
                Console.WriteLine("PRICE: " + xpathCompiler.EvaluateSingle("string(PRICE)", item));
            }

            */

            return result; 

        }

        static string DemoXPathMultiple(string parmFilename, string parmXPath)
        {

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

            // Load the source document
            //XdmNode input = processor.NewDocumentBuilder().Build(new Uri(samplesDir, "data/books.xml"));
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(parmFilename));

            // Create an XPath compiler
            XPathCompiler xpathCompiler = processor.NewXPathCompiler();

            // Enable caching, so each expression is only compiled once
            xpathCompiler.Caching = true;

            // Compile and evaluate some XPath expressions
            /*
            foreach (XdmItem item in xpathCompiler.Evaluate(parmXPath, input))
            {

                Console.WriteLine("TITLE: " + xpathCompiler.EvaluateSingle("string(TITLE)", item));
                Console.WriteLine("PRICE: " + xpathCompiler.EvaluateSingle("string(PRICE)", item));
            }
            */

            // use StringBuild to efficiently build and change a string result in the loop below 
            StringBuilder resultSB = new StringBuilder();
            int loopCounter = 0; 
            foreach (XdmItem item in xpathCompiler.Evaluate(parmXPath, input))
            {
                if (loopCounter++ > 0)
                   {
                    resultSB.Append(", "); 
                   }
                string tempResult = xpathCompiler.EvaluateSingle("string(.)", item).ToString(); 
                resultSB.Append(tempResult);  
            }

            return resultSB.ToString();

}

}  // end class 
}
</pre>

Input XML File

<pre>
<Reservation>
   <ConfirmationCode>QCOCD5</ConfirmationCode>
   <ConfirmationDate>2019-10-16T00:00:00</ConfirmationDate>
   <ExpirationDate>2019-10-10T00:00:00</ExpirationDate>
   <Passenger>Neal Walters</Passenger>
   <RapidRewards>2006721234</RapidRewards>
   <TicketNumber>5261499397436</TicketNumber>
   <PointsEarned>1367</PointsEarned>
   <AirlineIATACode>WN</AirlineIATACode>  
   <AirlineName>Southwest Airlines</AirlineName>
   <BaseFare>227.70</BaseFare>
   <USTransportationTax>17.08</USTransportationTax>
   <US911SecurityFee>11.20</US911SecurityFee>
   <USPassengerFacilityChg>12.30</USPassengerFacilityChg>
   <USFlightSegmentTax>13.50</USFlightSegmentTax>
   <EarlyBird>40.00</EarlyBird>
   <TotalPrice>321.78</TotalPrice>

   <Flight seq="1">
    <FlightLeg seq="1">
       <FlightNumber>1849</FlightNumber>
       <DepartureAirport>MDW</DepartureAirport>
       <ArrivalAirport>STL</ArrivalAirport>
       <DepartureDateTime>2019-11-02T19:20:00</DepartureDateTime>
       <ArrivalDateTime>2019-11-02T20:25:00</ArrivalDateTime>
    </FlightLeg>
    <FlightLeg seq="2">
       <FlightNumber>2105</FlightNumber>
       <DepartureAirport>STL</DepartureAirport>
       <ArrivalAirport>OKC</ArrivalAirport>
       <DepartureDateTime>2019-11-02T21:25:00</DepartureDateTime>
       <ArrivalDateTime>2019-11-02T22:50:00</ArrivalDateTime>
    </FlightLeg>
  </Flight>
   <Flight seq="2">
    <FlightLeg seq="1">
       <FlightNumber>4565</FlightNumber>
       <DepartureAirport>OKC</DepartureAirport>
       <ArrivalAirport>MDW</ArrivalAirport>
       <DepartureDateTime>2019-11-04T11:10:00</DepartureDateTime>
       <ArrivalDateTime>2019-11-04T13:05:00</ArrivalDateTime>
    </FlightLeg>
  </Flight>
</Reservation>
<pre>

Result

<pre>
result FlightNumber=1849
result FlightNumbers=1849, 2105, 4565
result XPath 3.0=WN-1849
</pre>

Leave a Reply