/// <summary> /// Analyse the package code for a single consignment. Calculate totals for the consignment based on that. /// Prepare for iterating the xml package elements one by one. /// </summary> /// <param name="PackageCode"></param> /// <param name="OutsideEU"></param> /// <param name="InvoiceValue"></param> public void MakePackages(string PackageCode, bool OutsideEU, double InvoiceValue, MyXMLDocument mydoc) { //start fresh PackageMultiples = new Dictionary <string, PackageMultiple>(); this.OutsideEU = OutsideEU; this.InvoiceValue = InvoiceValue; this.mydoc = mydoc; this.TotalItems = 0; this.TotalWeight = 0; this.TotalVolume = 0; //analyse package code string[] symbols = PackageCode.Split('+'); foreach (string s in symbols) { PackageDimensionsStore.PackageDimensions pak; if (!PackageDimensionsDict.TryGetValue(s, out pak)) { throw new InvalidOperationException("TNTPackageAnalyser: symbol " + s + ", as occuring in " + PackageCode + ", not found in Package Dimensions Dictionary."); } if (!PackageMultiples.ContainsKey(s)) { PackageMultiples.Add(s, new PackageMultiple(s, 1, pak)); } else { PackageMultiples[s].AddOne(); } TotalItems++; TotalWeight += pak.weight; TotalVolume += pak.volume; } ItemInvoiceValue = InvoiceValue / TotalItems; }
/// <summary> /// Navigate to a new position, relative to the navigation position of 'this' document. /// Returns new MyXMLDocument, it has no effects on the original one. /// </summary> /// <param name="xpath">relative XPath expression identifying a single node: the new navigation position</param> /// <returns>A partial clone of this doc, focussed on the new navigation position</returns> public MyXMLDocument Navigate(XPathExpression xpath) { MyXMLDocument doc2 = PartialClone(); doc2.nav = nav.SelectSingleNode(xpath); return(doc2); }
/// <summary> /// Lookup a Consignment by Id and make it current: ready for further reading. /// This one has a weaker assumption: either CREATE or SHIP must be there to have Consignments /// </summary> /// <param name="Id">Either a ConRef or a ConNumber, depending on the type of Id chosen, see constructor</param> /// <returns>success?</returns> public bool FindConsignmentById(string Id) { if (!hasCreate && !hasShip) { throw new InvalidOperationException("TNTResult: no CREATE and no SHIP element, therefore no consignment info."); } bool OK = true; if (hasCreate) { curCreate = createIndex.GetChildByIndexValue(Id); OK = OK && (curCreate != null); } if (hasBook) { curBook = bookIndex.GetChildByIndexValue(Id); OK = OK && (curBook != null); } if (hasShip) { curShip = shipIndex.GetChildByIndexValue(Id); OK = OK && (curShip != null); } return(OK); }
/// <summary> /// Transform an xml-document to a HttpContent request message that accords to the TNT spec. /// It has to be application/x-www-form-urlencoded ! /// It has to contain one key-value pair, "xml_in" being the key and the whole xml-string the value (urlencoded of course). /// The whole thing should be in UTF-8. /// </summary> /// <param name="xml">Xmldocument to send</param> private HttpContent BuildWWWFormUrlEncoded(MyXMLDocument xml) { Byte[] bytes; //First we get the xml to a stream... to make the XmlWriter believe it is boss of encoding (UTF-8) using (MemoryStream ms = new MemoryStream()) { xml.ToStream(ms, new UTF8Encoding(false, true), indent: true); bytes = ms.ToArray(); //not exactly the streaming + async philosophy, but we have to do some strange stuff } //Then we get the stream into a bytes array to enable us to do URL-encoding Byte[] bytes2 = HttpUtility.UrlEncodeToBytes(bytes); //We create an un-encoded namevaluepair, with bytes2 als the value string prolog = "xml_in="; Byte[] bytes3 = Encoding.UTF8.GetBytes(prolog); //Concatenate: bytes3 + bytes2 Byte[] bytes4 = new byte[bytes3.Length + bytes2.Length]; Buffer.BlockCopy(bytes3, 0, bytes4, 0, bytes3.Length); Buffer.BlockCopy(bytes2, 0, bytes4, bytes3.Length, bytes2.Length); //...all of this because we had to do URLEncoding at an unusual time, after writing the xml HttpContent content = new ByteArrayContent(bytes4); content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); return(content); }
public TNTShipRequest(DateTime CollectionDate, RequestTypes requestType, TNTPackageAnalyser pa, bool Debug = false) { this.reqestType = requestType; this.pa = pa; this.Debug = Debug; this.xml = new MyXMLDocument(); dateformatinfo = new DateTimeFormatInfo(); //neutral culture, it has / as date separator MakeFixedElements(CollectionDate); }
/// <summary> /// Constructor /// </summary> /// <param name="doc">MyXMLDocument that has a navigator focussed on the node whose children we want to index</param> /// <param name="multiChildName">Name of a node that may occur multiple times under the given node</param> public MyXMLChildIndex(MyXMLDocument doc, string multiChildName, XPathExpression propertyXPath) { this.index = new Dictionary <string, MyXMLDocument>(); var iter = new MyXMLChildEnumerable(doc, multiChildName); foreach (MyXMLDocument node in iter) { string key = node.nav.SelectSingleNode(propertyXPath).Value; index.Add(key, node); } }
/// <summary> /// Checks for unpleasant HTTP status codes as well as other problems with the response. /// All errors found here are fatal: they break the chain of async processes. /// </summary> /// <param name="content">HttpContent for Posting to TNT</param> /// <param name="expectXml">Do we expect the response to be XML?</param> private async Task <PostResults> PostAsync(HttpContent content, bool expectXml) { HttpResponseMessage resp = null; try { resp = await client.PostAsync(new Uri(TARGET_URL), content); } catch (Exception e) { FirePostError(0, "PostAsync Exception: " + e.Message); throw e; //just to stop the flow } if (!resp.IsSuccessStatusCode) { FirePostError(0, "HTTP error status " + resp.StatusCode + ": " + resp.ReasonPhrase); throw new InvalidOperationException("HTTP error status " + resp.StatusCode + ": " + resp.ReasonPhrase); } //xml checks if (expectXml) { MyXMLDocument xdoc = null; Stream st = await resp.Content.ReadAsStreamAsync(); try { TextReader rd = new StreamReader(st, new UTF8Encoding(false, true)); XmlReader XReader = XmlReader.Create(rd); xdoc = new MyXMLDocument(XReader, readOnly: true); if ( xdoc.NodeExists("/runtime_error") || xdoc.NodeExists("/parse_error") ) { string errormsg = xdoc.GetStringValue("//error_reason/text()"); FirePostError(0, "Errormessage sent by TNT: " + errormsg); throw new InvalidOperationException("Errormessage sent by TNT: " + errormsg); } } catch (Exception e) { FirePostError(0, "Problem parsing xml " + e.Message); throw e; } return(new PostResults(null, xdoc)); } else { string c = await resp.Content.ReadAsStringAsync(); return(new PostResults(c, null)); } }
//...other activities... /// <summary> /// Constructor /// </summary> /// <param name="doc">MyXMLDocument that contains the TNT Result, XML already parsed</param> /// <param name="indexBy">Shall we index the document by ConRef or by ConNumber?</param> public TNTResult(MyXMLDocument doc, IndexBy indexBy) { this.doc = doc; this.OK = Initialize(indexBy); }
/// <summary> /// Constructor /// </summary> /// <param name="reader">XmlReader that contains the TNT result</param> /// <param name="indexBy">Shall we index the document by ConRef or by ConNumber?</param> public TNTResult(XmlReader reader, IndexBy indexBy) { this.doc = new MyXMLDocument(reader, readOnly: true); this.OK = Initialize(indexBy); }
public PostResults(string Content, MyXMLDocument Xml) { this.Content = Content; this.Xml = Xml; }