// Returns collection of non-fixed (variable) fields from Marc21 record
        private IEnumerable <MetadataField> MarcGetVariableFields(MARC_Record record)
        {
            List <MetadataField> metadataFieldsList = new List <MetadataField>();

            // Step through each field in the collection
            foreach (int thisTag in record.Fields.Keys)
            {
                List <MARC_Field> matchingFields = record.Fields[thisTag];
                foreach (MARC_Field thisField in matchingFields)
                {
                    if (thisField.Subfield_Count != 0)
                    {
                        MetadataField metadataField = new MetadataField();
                        metadataField.TagName    = thisField.Tag.ToString().PadLeft(3, '0');
                        metadataField.Indicator1 = thisField.Indicator1.ToString();
                        metadataField.Indicator2 = thisField.Indicator2.ToString();
                        List <KeyValuePair <string, string> > subfields = new List <KeyValuePair <string, string> >();
                        // Build the complete line
                        foreach (MARC_Subfield thisSubfield in thisField.Subfields)
                        {
                            subfields.Add(new KeyValuePair <string, string>
                                              (thisSubfield.Subfield_Code.ToString(), thisSubfield.Data));
                        }
                        metadataField.Subfields = subfields;
                        metadataFieldsList.Add(metadataField);
                    }
                }
            }
            return(metadataFieldsList);
        }
        // Retrieves metadata from X-Server
        private void RetrieveMetadataByBarcodeXServer()
        {
            //create X-Server request
            string xServerUrl      = Settings.XServerUrl;
            string xServerBaseName = Settings.XServerBase;

            string errorText = "";

            if (string.IsNullOrWhiteSpace(xServerUrl))
            {
                errorText += "X-Server URL, ";
            }
            if (string.IsNullOrWhiteSpace(xServerBaseName))
            {
                errorText += "X-Server Database";
            }
            errorText = errorText.TrimEnd(new char[] { ' ', ',' });

            if (!string.IsNullOrEmpty(errorText))
            {
                throw new ArgumentException("V nastaveních chybí následující údaje: " + errorText);
            }

            string resultSetURLPart = "/X?op=find&code=BAR&request=" + this.barcode + "&base=" + xServerBaseName;
            string sysNoUrlPart     = "/X?op=present&set_entry=1&set_number=";

            if (!xServerUrl.StartsWith("http"))
            {
                xServerUrl = "https://" + xServerUrl;
            }
            // if /X is already in name, remove 'X'
            if (xServerUrl.EndsWith("/X"))
            {
                xServerUrl.TrimEnd('X');
            }
            // remove trailing '/'
            xServerUrl.TrimEnd('/');

            Metadata metadata = new Metadata();

            using (WebClient webClient = new WebClient())
            {
                Stream    stream          = webClient.OpenRead(xServerUrl + resultSetURLPart);
                XDocument doc             = XDocument.Load(stream);
                string    resultSetNumber = null;
                if (doc.Descendants("set_number").Count() > 0)
                {
                    resultSetNumber = doc.Descendants("set_number").Single().Value;
                }
                else
                {
                    throw new Z39Exception("Nenalezen vhodný záznam.");
                }

                stream = webClient.OpenRead(xServerUrl + sysNoUrlPart + resultSetNumber);
                doc    = XDocument.Load(stream);

                metadata.Sysno = doc.Descendants("doc_number").Single().Value;

                if (!string.IsNullOrWhiteSpace(metadata.Sysno))
                {
                    metadata.Custom = Settings.Base + metadata.Sysno;
                }

                IEnumerable <XElement> fixedFieldsXml = from el in doc.Descendants("fixfield")
                                                        select el;
                IEnumerable <XElement> variableFieldsXml = from el in doc.Descendants("varfield")
                                                           select el;

                List <KeyValuePair <string, string> > fixedFields = new List <KeyValuePair <string, string> >();
                foreach (var field in fixedFieldsXml)
                {
                    var name  = field.Attribute("id").Value;
                    var value = field.Value;
                    fixedFields.Add(new KeyValuePair <string, string>(name, value));
                }
                metadata.FixedFields = fixedFields;

                List <MetadataField> variableFields = new List <MetadataField>();
                foreach (var field in variableFieldsXml)
                {
                    MetadataField metadataField = new MetadataField();
                    metadataField.TagName    = field.Attribute("id").Value;
                    metadataField.Indicator1 = field.Attribute("i1").Value;
                    metadataField.Indicator2 = field.Attribute("i2").Value;
                    IEnumerable <KeyValuePair <string, string> > subfields = from sf in field.Elements("subfield")
                                                                             select new KeyValuePair <string, string>(sf.Attribute("label").Value, sf.Value);
                    metadataField.Subfields = subfields;
                    variableFields.Add(metadataField);
                }
                metadata.VariableFields = variableFields;

                // Title
                foreach (var field in Settings.MetadataTitleFields)
                {
                    foreach (var subfield in field.Value)
                    {
                        metadata.Title += ParseMetadataFromOaiXml(doc, new Tuple <int, char, int?, int?>(field.Key, subfield, null, null)) + " ";
                    }
                    metadata.Title = metadata.Title.Trim();
                }

                // Authors
                string authors = "";
                foreach (var field in Settings.MetadataAuthorFields)
                {
                    foreach (var subfield in field.Value)
                    {
                        authors += ParseMetadataFromOaiXml(doc, new Tuple <int, char, int?, int?>(field.Key, subfield, null, null)) + "@";
                    }
                    authors = authors.Trim(new char[] { '@', ' ' }) + "|";
                }
                metadata.Authors = ParseAuthors(authors, '@');
                metadata.Year    = ParseMetadataFromOaiXml(doc, Settings.MetadataPublishYearField);
                ParseIdentifierFromOaiXml(doc, ref metadata);
            }
            this.Metadata = metadata;
        }