public void VariantWith2Traits()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var variant = new LexVariant();
				variant.SetAlternative("etr", "one");
				variant.Traits.Add(new LexTrait("a", "A"));
				variant.Traits.Add(new LexTrait("b", "B"));
				session.LiftWriter.AddVariant(variant);
				session.LiftWriter.End();
				AssertHasOneMatch("variant/trait[@name='a' and @value='A']", session);
				AssertHasOneMatch("variant/trait[@name='b' and @value='B']", session);
			}
		}
		public void Add_CultureUsesPeriodForTimeSeparator_DateAttributesOutputWithColon()
		{
			var culture = new CultureInfo("en-US");
			culture.DateTimeFormat.TimeSeparator = ".";

			Thread.CurrentThread.CurrentCulture = culture;

			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				entry.LexicalForm["test"] = "lexicalForm";
				// make dateModified different than dateCreated
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				string result = session.StringBuilder.ToString();
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath(
					String.Format("//entry[@dateModified=\"{0}\"]",
								  entry.ModificationTime.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture))
					);
				Assert.IsTrue(result.Contains(":"), "should contain colons");
				Assert.IsFalse(result.Contains("."), "should not contain periods");
			}
		}
		public void ExampleSentenceWithTranslation()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var example = new LexExampleSentence();
				example.Sentence["blue"] = "ocean's eleven";
				example.Sentence["red"] = "red sunset tonight";
				example.Translation["green"] = "blah blah";
				session.LiftWriter.Add(example);
				var outPut = session.OutputString();
				AssertEqualsCanonicalString(
					"<example><form lang=\"blue\"><text>ocean's eleven</text></form><form lang=\"red\"><text>red sunset tonight</text></form><translation><form lang=\"green\"><text>blah blah</text></form></translation></example>", outPut);
			}
		}
		public void EntryGuid()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				string result = session.StringBuilder.ToString();
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath(String.Format("//entry[@guid=\"{0}\"]", entry.Guid));
			}
		}
		public void EntryHasDateCreated()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				string result = session.StringBuilder.ToString();
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath(
					String.Format("//entry[@dateCreated=\"{0}\"]", entry.CreationTime.ToString("yyyy-MM-ddTHH:mm:ssZ"))
				);
			}
		}
		public void Entry_EntryHasIdWithInvalidXMLCharacters_CharactersEscaped()
		{
			const string expected = "id=\"&lt;&gt;&amp;&quot;'\"";
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var entry = session.CreateItem();
				// technically the only invalid characters in an attribute are & < and " (when surrounded by ")
				entry.Id = "<>&\"\'";
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				string result = session.OutputString();
				Assert.IsTrue(result.Contains(expected));
			}
		}
		public void Entry_HasId_RemembersId()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				entry.Id = "my id";
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				string result = session.StringBuilder.ToString();
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath("//entry[@id='my id']");
			}
		}
		public void CustomOptionRefCollectionOnExample()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				//_fieldToOptionListName.Add("flubs", "colors");
				var example = new LexExampleSentence();
				var o = example.GetOrCreateProperty<OptionRefCollection>("flubs");
				o.AddRange(new[] {"orange", "blue"});
				session.LiftWriter.Add(example);
				session.LiftWriter.End();
				string expected = CanonicalXml.ToCanonicalStringFragment(
					"<example><trait name=\"flubs\" value=\"orange\" /><trait name=\"flubs\" value=\"blue\" /></example>"
				);
				Assert.AreEqual(
					expected,
					session.StringBuilder.ToString()
				);
			}
		}
		public void CustomOptionRefOnEntry()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				//_fieldToOptionListName.Add("flub", "kindsOfFlubs");
				LexEntry entry = session.CreateItem();

				var o = entry.GetOrCreateProperty<OptionRef>("flub");
				o.Value = "orange";
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch(
					"entry/trait[@name='flub' and @value='orange']",
					session
				);
			}
		}
		public void CustomMultiTextOnSense()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var sense = new LexSense();
				var m = sense.GetOrCreateProperty<MultiText>("flubadub");
				m["zz"] = "orange";
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("sense/field[@type='flubadub']/form[@lang='zz' and text='orange']", session);
			}
		}
		public void CustomOptionRefCollectionOnEntry()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				//_fieldToOptionListName.Add("flubs", "colors");
				LexEntry entry = session.CreateItem();

				var o = entry.GetOrCreateProperty<OptionRefCollection>("flubs");
				o.AddRange(new[] {"orange", "blue"});
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("entry/trait[@name='flubs' and @value='orange']", session);
				AssertHasAtLeastOneMatch("entry/trait[@name='flubs' and @value='blue']", session);
				AssertHasAtLeastOneMatch("entry[count(trait) =2]", session);
			}
		}
		public void CustomMultiTextOnEntry()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var entry = session.CreateItem();

				var m = entry.GetOrCreateProperty<MultiText>("flubadub");
				m["zz"] = "orange";
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("entry/field[@type='flubadub']/form[@lang='zz' and text='orange']", session);
			}
		}
		public void FieldWithTraits()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var variant = new LexVariant();
				variant.SetAlternative("etr", "one");
				var fieldA = new LexField("a");
				fieldA.SetAlternative("en", "aaa");
				fieldA.Traits.Add(new LexTrait("one", "1"));
				variant.Fields.Add(fieldA);
				session.LiftWriter.AddVariant(variant);
				session.LiftWriter.End();
				AssertHasOneMatch("variant/field[@type='a']/trait[@name='one' and @value='1']", session);
			}
		}
		public void VariantWith2SimpleFields()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var variant = new LexVariant();
				variant.SetAlternative("etr", "one");
				var fieldA = new LexField("a");
				fieldA.SetAlternative("en", "aaa");
				variant.Fields.Add(fieldA);
				var fieldB = new LexField("b");
				fieldB.SetAlternative("en", "bbb");
				variant.Fields.Add(fieldB);
				session.LiftWriter.AddVariant(variant);
				session.LiftWriter.End();
				AssertHasOneMatch("variant/field[@type='a']/form[@lang='en' and text = 'aaa']", session);
				AssertHasOneMatch("variant/field[@type='b']/form[@lang='en' and text = 'bbb']", session);
			}
		}
		public void EmptyExampleSource_NoAttribute()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var ex = new LexExampleSentence();
				ex.GetOrCreateProperty<OptionRef>(
					LexExampleSentence.WellKnownProperties.Source
				);
				session.LiftWriter.Add(ex);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("example[not(@source)]", session);
			}
		}
		public void CustomOptionRefOnSense()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				//_fieldToOptionListName.Add("flub", "kindsOfFlubs");
				var sense = new LexSense();
				var o = sense.GetOrCreateProperty<OptionRef>("flub");
				o.Value = "orange";
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				string expected = CanonicalXml.ToCanonicalStringFragment(
					GetSenseElement(sense) + "<trait name=\"flub\" value=\"orange\" /></sense>"
				);
				Assert.AreEqual(
					expected,
					session.StringBuilder.ToString()
				);
			}
		}
		public void EmptyNoteOnEntry_NoOutput()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				entry.GetOrCreateProperty<MultiText>(PalasoDataObject.WellKnownProperties.Note);
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("entry[not(note)]", session);
				AssertHasAtLeastOneMatch("entry[not(field)]", session);
			}
		}
		public void CustomOptionRefOnSenseWithGrammi()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				//_fieldToOptionListName.Add("flub", "kindsOfFlubs");
				var sense = new LexSense();
				var grammi = sense.GetOrCreateProperty<OptionRef>(
					LexSense.WellKnownProperties.PartOfSpeech
				);
				grammi.Value = "verb";

				var o = sense.GetOrCreateProperty<OptionRef>("flub");
				o.Value = "orange";
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("sense/trait[@name='flub' and @value='orange']", session);
				AssertHasAtLeastOneMatch("sense[count(trait)=1]", session);
			}
		}
		public void Entry_ScaryUnicodeCharacter_SafeXmlEmitted()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				entry.LexicalForm["test"] = '\u001F'.ToString();
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();

				var doc = new XmlDocument();
				//this next line will crash if things aren't safe
				doc.LoadXml(session.StringBuilder.ToString());
			}
		}
		public void DefinitionOnSense_OutputAsDefinition()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var sense = new LexSense();
				var m = sense.GetOrCreateProperty<MultiText>(
					LexSense.WellKnownProperties.Definition
				);
				m["zz"] = "orange";
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("sense/definition/form[@lang='zz']/text[text()='orange']", session);
				AssertHasAtLeastOneMatch("sense[not(field)]", session);
			}
		}
		public void Entry_NoId_GetsHumanReadableId()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var entry = session.CreateItem();
				entry.LexicalForm["test"] = "lexicalForm";
				//_lexEntryRepository.SaveItem(entry);
				// make dateModified different than dateCreated
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();

				string expectedId = LiftWriter.GetHumanReadableIdWithAnyIllegalUnicodeEscaped(
					entry, new Dictionary<string, int>()
				);
				string result = session.StringBuilder.ToString();
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath(String.Format("//entry[@id=\"{0}\"]", expectedId));
			}
		}
		public void DeletedEntry()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var entry = new LexEntry();
				session.LiftWriter.AddDeletedEntry(entry);
				session.LiftWriter.End();
				Assert.IsNotNull(GetStringAttributeOfTopElement("dateDeleted", session));
			}
		}
		public void EmptyRelationNotOutput()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				entry.AddRelationTarget(LexEntry.WellKnownProperties.BaseForm, string.Empty);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				Assert.IsFalse(session.StringBuilder.ToString().Contains("relation"));
			}
		}
		public void EmptyCustomMultiText()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var sense = new LexSense();
				sense.GetOrCreateProperty<MultiText>("flubadub");
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("sense[not(field)]", session);
			}
		}
		public void EntryHasDateModified()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				entry.LexicalForm["test"] = "lexicalForm";
				// make dateModified different than dateCreated
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				string result = session.StringBuilder.ToString();
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath(
					String.Format("//entry[@dateModified=\"{0}\"]", entry.ModificationTime.ToString("yyyy-MM-ddTHH:mm:ssZ"))
				);
			}
		}
		public void EmptyCustomOptionRefCollection()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var sense = new LexSense();
				sense.GetOrCreateProperty<OptionRefCollection>("flubadub");
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("sense[not(trait)]", session);
			}
		}
		public void EntryWithSenses()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexEntry entry = session.CreateItem();
				entry.LexicalForm["blue"] = "ocean";
				LexSense sense1 = new LexSense();
				sense1.Gloss["a"] = "aaa";
				entry.Senses.Add(sense1);
				LexSense sense2 = new LexSense();
				sense2.Gloss["b"] = "bbb";
				entry.Senses.Add(sense2);
				//_lexEntryRepository.SaveItem(entry);
				session.LiftWriter.Add(entry);
				session.LiftWriter.End();
				string result = session.StringBuilder.ToString();
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath("//entry/sense/gloss[@lang='a']/text[text()='aaa']");
				AssertThatXmlIn.String(result).HasAtLeastOneMatchForXpath("//entry/sense/gloss[@lang='b']/text[text()='bbb']");
				AssertHasAtLeastOneMatch("entry[count(sense)=2]", session);
			}
		}
		public void EmptyDefinitionOnSense_NotOutput()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var sense = new LexSense();
				sense.GetOrCreateProperty<MultiText>(LexSense.WellKnownProperties.Definition);
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("sense[not(definition)]", session);
				AssertHasAtLeastOneMatch("sense[not(field)]", session);
			}
		}
		public void ExampleSourceAsAttribute()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				LexExampleSentence ex = new LexExampleSentence();
				OptionRef z = ex.GetOrCreateProperty<OptionRef>(
					LexExampleSentence.WellKnownProperties.Source
				);
				z.Value = "hearsay";

				session.LiftWriter.Add(ex);
				session.LiftWriter.End();
				AssertHasAtLeastOneMatch("example[@source='hearsay']", session);
			}
		}
		public void EntryWithTypedNote()
		{
			using (var session = new LiftExportAsFragmentTestSession())
			{
				var sense = new LexSense();
				var note = new LexNote("comic");
				note.SetAlternative("etr", "one");
				sense.Notes.Add(note);
				session.LiftWriter.Add(sense);
				session.LiftWriter.End();
				AssertHasOneMatch("sense/note/form[@lang='etr' and text='one']", session);
				AssertHasOneMatch("sense/note[@type='comic']", session);
			}
		}