private string GetAvailableUid(Uid uid) { string availableUid; // copy the ID if available if (uid.FrameworkElementName != null && (!_uidTable.Contains(uid.FrameworkElementName)) ) { availableUid = uid.FrameworkElementName; } else { // generate a new id string sequence = GetElementLocalName(uid.ElementName); Int64 index; if (_sequenceMaxIds.Contains(sequence)) { index = (Int64) _sequenceMaxIds[sequence]; if (index == Int64.MaxValue) { // this sequence reaches the max // we fallback to create a new sequence index = -1; while (index < 0) { sequence = (_uidSequenceFallbackCount == 0) ? UidFallbackSequence : UidFallbackSequence + _uidSequenceFallbackCount; if (_sequenceMaxIds.Contains(sequence)) { index = (Int64) _sequenceMaxIds[sequence]; if (index < Int64.MaxValue) { // found the fallback sequence with valid index index ++; break; } } else { // create a new sequence from 1 index = 1; break; } _uidSequenceFallbackCount ++; } } else { index ++; } } else { // a new sequence index = 1; } availableUid = sequence + UidSeparator + index; } // store the uid so that it won't be used again StoreUid(availableUid); return availableUid; }
/// <summary> /// Parse the input file and get all the information of Uids /// </summary> /// <param name="fileName">input file</param> /// <returns>UidCollector containing all the information for the Uids in the file</returns> private UidCollector ParseFile(string fileName) { UidCollector collector = new UidCollector(fileName ); using (Stream xamlStream = File.OpenRead(fileName)) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext( null, // nametable nsmgr, // namespace manager null, // xml:Lang scope XmlSpace.Default // XmlSpace ); XmlTextReader reader = new XmlTextReader( xamlStream, // xml stream XmlNodeType.Document, // parsing document context // parser context ); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element : { if (collector.RootElementLineNumber < 0) { collector.RootElementLineNumber = reader.LineNumber; collector.RootElementLinePosition = reader.LinePosition; } if (reader.Name.IndexOf('.') >= 0) { // the name has a dot, which suggests it is a property tag. // we will ignore adding uid continue; } Uid currentUid = new Uid( reader.LineNumber, reader.LinePosition + reader.Name.Length, reader.Name, SpaceInsertion.BeforeUid // insert space before the Uid ); ; if (reader.HasAttributes) { reader.MoveToNextAttribute(); // As a heuristic to better preserve the source file, add uid to the place of the // first attribute currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; currentUid.Space = SpaceInsertion.AfterUid; do { string namespaceUri = nsmgr.LookupNamespace(reader.Prefix); if (reader.LocalName == XamlReaderHelper.DefinitionUid && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Uid attribute, store the actual value and position currentUid.Value = reader.Value; currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefaultNamespaceURI) { // found Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.Prefix == "xmlns") { // found a namespace declaration, store the namespace prefix // so that when we need to add a new namespace declaration later // we won't reuse the namespace prefix. collector.AddNamespacePrefix(reader.LocalName); } } while (reader.MoveToNextAttribute()); } if (currentUid.Value == null) { // there is no x:Uid found on this element, we need to resolve the // namespace prefix in order to add the Uid string prefix = nsmgr.LookupPrefix(XamlReaderHelper.DefinitionNamespaceURI); if (prefix != string.Empty) currentUid.NamespacePrefix = prefix; } collector.AddUid(currentUid); break; } } } } return collector; }
// add the uid to the collector public void AddUid(Uid uid) { _uids.Add(uid); // set the uid status according to the raw data if (uid.Value == null) { uid.Status = UidStatus.Absent; } else if (_uidTable.Contains(uid.Value)) { uid.Status = UidStatus.Duplicate; } else { // valid uid, store it StoreUid(uid.Value); } }
private void WriteNewUid(Uid uid) { // construct the attribute name, e.g. x:Uid // "x" will be the resolved namespace prefix for the definition namespace string attributeName = (uid.NamespacePrefix == null) ? _collector.NamespaceAddedForMissingUid + ":" + XamlReaderHelper.DefinitionUid : uid.NamespacePrefix + ":" + XamlReaderHelper.DefinitionUid; // escape all the Xml entities in the value string attributeValue = EscapedXmlEntities.Replace( uid.Value, EscapeMatchEvaluator ); string clause = string.Format( TypeConverterHelper.InvariantEnglishUS, "{0}=\"{1}\"", attributeName, attributeValue ); _targetWriter.Write(clause); }