private List <CustomOrderedTerm> ProcessCustomSortOrder(LocalTermContainer termContainer, XElement containerElement) { // Can we use the InOrder attribute instead of the CustomSortOrder element? // To do that, we need to find a child term for each CustomSortOrder GUID // and return them, followed by the rest of the terms. If we can't find // a child term, then we fall back to writing the "CustomSortOrder" element // instead. var childTermsById = termContainer.Terms .Where(x => x.Id != Guid.Empty) .ToDictionary(x => x.Id); var resortedOrderedTerms = new List <CustomOrderedTerm>(); foreach (var sortedId in termContainer.CustomSortOrder) { LocalTerm term; if (childTermsById.TryGetValue(sortedId, out term)) { resortedOrderedTerms.Add(new CustomOrderedTerm(term, writeInOrderAttribute: true)); } else { // An ID is missing, so fall back to using the "CustomSortOrder" element instead var customSortOrderElement = new XElement(TaxmlSpec.CustomSortOrderToken); containerElement.Add(customSortOrderElement); foreach (Guid itemId in termContainer.CustomSortOrder) { customSortOrderElement.Add( new XElement(TaxmlSpec.ItemToken, new XAttribute(TaxmlSpec.IdToken, itemId.ToString("B")) ) ); } // Set writeInOrderAttribute=false for all terms, since we're // using the "CustomSortOrder" element return(termContainer.Terms .Select(x => new CustomOrderedTerm(x, writeInOrderAttribute: false)) .ToList()); } } var sortedIds = new HashSet <Guid>(termContainer.CustomSortOrder); foreach (var term in termContainer.Terms) { if (!sortedIds.Contains(term.Id)) { resortedOrderedTerms.Add(new CustomOrderedTerm(term, writeInOrderAttribute: false)); } } return(resortedOrderedTerms); }
private void ProcessInOrderList(LocalTermContainer termContainer, List <Guid> inOrderList, XNode xmlNodeForError) { if (inOrderList.Count > 0) { if (termContainer.CustomSortOrder.Count > 0) { throw new ParseException( "The InOrder attribute cannot be used when the container has a CustomSortOrder element", xmlNodeForError); } termContainer.CustomSortOrder.AssignFrom(inOrderList); } }
protected override void SetParentItem(LocalTaxonomyItem value) { this.ParentItem = (LocalTermContainer)value; }
private void ProcessTerm(XElement xmlNode, LocalTermContainer parentTermContainer, List <Guid> parentInOrderList, bool isTermLink) { LocalTerm term; Guid id = this.GetGuidAttributeValue(xmlNode, TaxmlSpec.IdToken) ?? Guid.Empty; if (isTermLink) { string nameHint = this.GetAttributeValue(xmlNode, TaxmlSpec.NameHintToken) ?? ""; string termLinkSourcePath = this.GetAttributeValue(xmlNode, TaxmlSpec.TermLinkSourcePathToken) ?? ""; if (id == Guid.Empty && string.IsNullOrWhiteSpace(termLinkSourcePath)) { throw new ParseException( "TermLink elements must have either the ID attribute or the TermLinkSourcePath attribute", xmlNode); } if (termLinkSourcePath.Length > 0) { term = LocalTerm.CreateTermLinkUsingPath(parentTermContainer.DefaultLanguageLcid, termLinkSourcePath); } else { term = LocalTerm.CreateTermLinkUsingId(id, parentTermContainer.DefaultLanguageLcid, nameHint); } } else { string name = this.GetRequiredAttributeValue(xmlNode, TaxmlSpec.NameToken); term = LocalTerm.CreateTerm(id, name, parentTermContainer.DefaultLanguageLcid); } this.ReadTaxmlComments(xmlNode, term); bool?isAvailableForTagging = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.IsAvailableForTaggingToken); if (isAvailableForTagging.HasValue) { term.IsAvailableForTagging = isAvailableForTagging.Value; } if (isTermLink) { bool?isPinnedRoot = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.IsPinnedRootToken); if (isPinnedRoot.HasValue) { term.IsPinnedRoot = isPinnedRoot.Value; } } else { string owner = this.GetAttributeValue(xmlNode, TaxmlSpec.OwnerToken); if (owner != null) { term.Owner = owner; } bool?isDeprecated = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.IsDeprecatedToken); if (isDeprecated.HasValue) { term.IsDeprecated = isDeprecated.Value; } } bool inOrder = this.GetBooleanAttributeValue(xmlNode, TaxmlSpec.InOrderToken) ?? false; if (inOrder) { if (term.Id == Guid.Empty) { throw new ParseException("The InOrder attribute cannot be used when the term ID is empty", xmlNode); } parentInOrderList.Add(term.Id); } // Add the term set to the parent term / term set parentTermContainer.AddTerm(term); var inOrderList = new List <Guid>(); foreach (XElement childNode in xmlNode.Elements()) { switch (childNode.Name.LocalName) { case TaxmlSpec.LocalizedDescriptionToken: int descriptionLcid = this.GetLcidFromLanguageAttribute(childNode, term); term.SetDescription(childNode.Value, descriptionLcid); break; case TaxmlSpec.CustomPropertyToken: this.ProcessCustomProperty(term.CustomProperties, childNode); break; case TaxmlSpec.LocalCustomPropertyToken: this.ProcessCustomProperty(term.LocalCustomProperties, childNode); break; case TaxmlSpec.CustomSortOrderToken: this.ProcessCustomSortOrder(term.CustomSortOrder, childNode); break; case TaxmlSpec.LabelToken: int labelLcid = this.GetLcidFromLanguageAttribute(childNode, term); bool?setAsDefaultLabel = this.GetBooleanAttributeValue(childNode, TaxmlSpec.IsDefaultForLanguageToken); term.AddLabel(childNode.Value, labelLcid, setAsDefaultLabel ?? false); break; case TaxmlSpec.TermToken: this.ProcessTerm(childNode, term, inOrderList, isTermLink: false); break; case TaxmlSpec.TermLinkToken: this.ProcessTerm(childNode, term, inOrderList, isTermLink: true); break; case TaxmlSpec.SyncActionToken: this.ProcessSyncAction(childNode, term); break; default: throw new ParseException("Unimplemented XML tag \"" + childNode.Name.LocalName + "\"", childNode); } } this.ProcessInOrderList(term, inOrderList, xmlNode); }
private void ProcessChildTerms(XElement termContainerElement, LocalTermContainer termContainer, List <CustomOrderedTerm> orderedTerms) { LocalTermStore termStore = termContainer.GetTermStore(); foreach (CustomOrderedTerm customOrderedTerm in orderedTerms) { LocalTerm term = customOrderedTerm.Term; bool isTermLink = term.TermKind != LocalTermKind.NormalTerm; XElement termElement; if (isTermLink) { termElement = new XElement(TaxmlSpec.TermLinkToken); if (term.TermKind == LocalTermKind.TermLinkUsingId && term.TermLinkNameHint.Length > 0) { termElement.Add(new XAttribute(TaxmlSpec.NameHintToken, term.TermLinkNameHint)); } } else { termElement = new XElement(TaxmlSpec.TermToken, new XAttribute(TaxmlSpec.NameToken, term.Name)); } termContainerElement.Add(termElement); this.ProcessTaxmlComments(termElement, term); if (term.Id != Guid.Empty) { termElement.Add(new XAttribute(TaxmlSpec.IdToken, term.Id.ToString("B"))); } if (customOrderedTerm.WriteInOrderAttribute) { if (termContainer.CustomSortOrder.Contains(term.Id)) { termElement.Add(new XAttribute(TaxmlSpec.InOrderToken, true)); } } if (!term.IsAvailableForTagging) { termElement.Add(new XAttribute(TaxmlSpec.IsAvailableForTaggingToken, false)); } this.ProcessSyncActionElement(term, termElement); if (isTermLink) { if (!string.IsNullOrWhiteSpace(term.TermLinkSourcePath)) { termElement.Add(new XAttribute(TaxmlSpec.TermLinkSourcePathToken, term.TermLinkSourcePath)); } if (term.IsPinnedRoot) { termElement.Add(new XAttribute(TaxmlSpec.IsPinnedRootToken, true)); } } else { // TODO: If the Term.Owner is the same as the parent object, can we omit it? if (!string.IsNullOrEmpty(term.Owner)) { termElement.Add(new XAttribute(TaxmlSpec.OwnerToken, term.Owner)); } if (term.IsDeprecated) { termElement.Add(new XAttribute(TaxmlSpec.IsDeprecatedToken, true)); } foreach (LocalizedString description in term.Descriptions) { XElement descriptionElement = new XElement(TaxmlSpec.LocalizedDescriptionToken, description); termElement.Add(descriptionElement); if (description.Lcid != term.DefaultLanguageLcid) { descriptionElement.Add(new XAttribute(TaxmlSpec.LanguageToken, description.Lcid)); descriptionElement.Value = description.Value; } } this.ProcessCustomProperties(term.CustomProperties, termElement, isLocal: false); } this.ProcessCustomProperties(term.LocalCustomProperties, termElement, isLocal: true); List <CustomOrderedTerm> orderedChildTerms = this.ProcessCustomSortOrder(term, termElement); if (!isTermLink) { foreach (LocalTermLabel label in term.Labels) { // If this is the Term.Name label, then it doesn't need to be specified explicitly if (label.IsDefault && label.Lcid == term.DefaultLanguageLcid) { continue; } XElement labelElement = new XElement(TaxmlSpec.LabelToken, label.Value); termElement.Add(labelElement); if (label.Lcid != term.DefaultLanguageLcid) { labelElement.Add(new XAttribute(TaxmlSpec.LanguageToken, label.Lcid)); } if (label.IsDefault) { labelElement.Add(new XAttribute(TaxmlSpec.IsDefaultForLanguageToken, true)); } } } this.ProcessChildTerms(termElement, term, orderedChildTerms); } }
private static void ProcessCsvLines(LocalTermGroup termGroup, CsvReader csvReader) { int columnTermSetName = csvReader.GetColumnIndex("Term Set Name"); int columnTermSetDescription = csvReader.GetColumnIndex("Term Set Description"); int columnLcid = csvReader.GetColumnIndex("LCID"); int columnAvailableForTagging = csvReader.GetColumnIndex("Available for Tagging"); int columnTermDescription = csvReader.GetColumnIndex("Term Description"); int[] columnTermLabels = { csvReader.GetColumnIndex("Level 1 Term"), csvReader.GetColumnIndex("Level 2 Term"), csvReader.GetColumnIndex("Level 3 Term"), csvReader.GetColumnIndex("Level 4 Term"), csvReader.GetColumnIndex("Level 5 Term"), csvReader.GetColumnIndex("Level 6 Term"), csvReader.GetColumnIndex("Level 7 Term") }; LocalTermSet termSet = null; while (csvReader.ReadNextLine()) { // Is it a blank row? if (csvReader.Values.All(x => string.IsNullOrWhiteSpace(x))) { // Yes, skip it continue; } string termSetName = csvReader[columnTermSetName].Trim(); string termSetDescription = csvReader[columnTermSetDescription].Trim(); string lcidString = csvReader[columnLcid].Trim(); int currentLcid; if (!int.TryParse(lcidString, out currentLcid)) { currentLcid = termGroup.DefaultLanguageLcid; } bool availableForTagging = true; if (!string.IsNullOrWhiteSpace(csvReader[columnAvailableForTagging])) { availableForTagging = bool.Parse(csvReader[columnAvailableForTagging]); } string termDescription = csvReader[columnTermDescription].Trim(); var termLabels = new List <string>(); for (int i = 0; i < columnTermLabels.Length; ++i) { int columnIndex = columnTermLabels[i]; if (columnIndex < csvReader.Values.Count) { string value = csvReader[columnIndex].Trim(); if (string.IsNullOrEmpty(value)) { break; } termLabels.Add(value); } } if (!string.IsNullOrEmpty(termSetName)) { termSet = termGroup.AddTermSet(Guid.Empty, termSetName); termSet.SetName(termSetName, currentLcid); termSet.Description = termSetDescription; } if (termSet != null) { LocalTermContainer parent = termSet; if (termLabels.Count == 0) { throw new Exception("Missing term label"); } foreach (string parentTermLabel in termLabels.Take(termLabels.Count - 1)) { LocalTerm newParent; if (!parent.Terms.TryGetByName(parentTermLabel, currentLcid, out newParent)) { throw new Exception("No match found for parent term \"" + parentTermLabel + "\""); } parent = newParent; } string termLabel = termLabels.Last(); LocalTerm term = parent.AddTerm(Guid.Empty, termLabel); term.SetName(termLabel, currentLcid); term.SetDescription(termDescription, currentLcid); term.IsAvailableForTagging = availableForTagging; } } }