Exemple #1
0
        //[DebuggerStepThrough()]
        public static XmlState ProcessFragment(ITextSource fragment, Func <XmlReader, int, XmlState, bool> processor)
        {
            var lineOffsets = new List <int>()
            {
                0
            };
            var state          = XmlState.Other;
            var line           = 1;
            var lastTag        = new KeyValuePair <int, int>(0, 0);
            var attrValueQuote = '"';

            for (var i = 0; i < fragment.TextLength; i++)
            {
                switch (fragment.GetCharAt(i))
                {
                case '\r':
                    if (i + 1 < fragment.TextLength && fragment.GetCharAt(i + 1) == '\n')
                    {
                        i++;
                    }
                    line++;
                    lineOffsets.Add(i + 1);
                    if (state == XmlState.Tag)
                    {
                        state = XmlState.Attribute;
                    }
                    break;

                case '\n':
                    line++;
                    lineOffsets.Add(i + 1);
                    if (state == XmlState.Tag)
                    {
                        state = XmlState.Attribute;
                    }
                    break;

                default:
                    switch (state)
                    {
                    case XmlState.Attribute:
                        if (fragment.GetCharAt(i) == '=')
                        {
                            i++;
                            if (i < fragment.TextLength)
                            {
                                attrValueQuote = fragment.GetCharAt(i);
                            }
                            state = XmlState.AttributeValue;
                        }
                        else if (fragment.GetCharAt(i) == '>')
                        {
                            state = XmlState.Other;
                        }
                        break;

                    case XmlState.AttributeValue:
                        if (fragment.GetCharAt(i) == '"' || fragment.GetCharAt(i) == '\'')
                        {
                            state = XmlState.Tag;
                        }
                        break;

                    case XmlState.CData:
                        if (i + 2 < fragment.TextLength && fragment.GetCharAt(i) == ']' && fragment.GetCharAt(i + 1) == ']' && fragment.GetCharAt(i + 2) == '>')
                        {
                            i    += 2;
                            state = XmlState.Other;
                        }
                        break;

                    case XmlState.Comment:
                        if (i + 2 < fragment.TextLength && fragment.GetCharAt(i) == '-' && fragment.GetCharAt(i + 1) == '-' && fragment.GetCharAt(i + 2) == '>')
                        {
                            i    += 2;
                            state = XmlState.Other;
                        }
                        break;

                    case XmlState.Tag:
                        if (char.IsWhiteSpace(fragment.GetCharAt(i)))
                        {
                            state = XmlState.Attribute;
                        }
                        else if (fragment.GetCharAt(i) == '>')
                        {
                            state = XmlState.Other;
                        }
                        break;

                    case XmlState.Other:
                        if (fragment.GetCharAt(i) == '<')
                        {
                            if (i + 3 < fragment.TextLength &&
                                fragment.GetCharAt(i + 1) == '!' &&
                                fragment.GetCharAt(i + 2) == '-' &&
                                fragment.GetCharAt(i + 3) == '-')
                            {
                                i    += 3;
                                state = XmlState.Comment;
                            }
                            else if (i + 8 < fragment.TextLength &&
                                     fragment.GetCharAt(i + 1) == '!' &&
                                     fragment.GetCharAt(i + 2) == '[' &&
                                     fragment.GetCharAt(i + 3) == 'C' &&
                                     fragment.GetCharAt(i + 4) == 'D' &&
                                     fragment.GetCharAt(i + 5) == 'A' &&
                                     fragment.GetCharAt(i + 6) == 'T' &&
                                     fragment.GetCharAt(i + 7) == 'A' &&
                                     fragment.GetCharAt(i + 8) == '[')
                            {
                                i    += 8;
                                state = XmlState.CData;
                            }
                            else
                            {
                                state   = XmlState.Tag;
                                lastTag = new KeyValuePair <int, int>(line, i - lineOffsets.Last() + 2);
                            }
                        }
                        break;
                    }
                    break;
                }
            }

            const string __noName = "___NO_NAME___";
            const string __eof    = "{`EOF`}";
            var          suffix   = string.Empty;

            switch (state)
            {
            case XmlState.Attribute:
                if (char.IsWhiteSpace(fragment.GetCharAt(fragment.TextLength - 1)))
                {
                    state   = XmlState.AttributeStart;
                    suffix += ">";
                }
                else
                {
                    suffix += "=\"\">";
                }
                break;

            case XmlState.AttributeValue:
                if (fragment.GetCharAt(fragment.TextLength - 1) == '=')
                {
                    suffix += "''>";
                }
                else
                {
                    suffix += attrValueQuote.ToString() + ">";
                }
                break;

            case XmlState.CData:
                suffix += "]]>";
                break;

            case XmlState.Comment:
                suffix += "-->";
                break;

            case XmlState.Tag:
                if (fragment.GetCharAt(fragment.TextLength - 1) == '<')
                {
                    suffix += __noName;
                }
                suffix += ">";
                break;
            }
            suffix += "<!--" + __eof + "-->";

            var settings = new XmlReaderSettings()
            {
                ConformanceLevel = ConformanceLevel.Fragment
            };
            var textReader = new AugmentedReader(fragment.CreateReader(), suffix);
            var reader     = XmlReader.Create(textReader, settings);
            var lineInfo   = reader as IXmlLineInfo;

            try
            {
                bool keepGoing = true;
                while (keepGoing && reader.Read() && !(reader.NodeType == XmlNodeType.Comment && reader.Value == __eof))
                {
                    if (reader.LocalName != __noName)
                    {
                        keepGoing = processor.Invoke(reader, lineOffsets[lineInfo.LineNumber - 1]
                                                     + lineInfo.LinePosition
                                                     - (reader.NodeType == XmlNodeType.Element ? 2 : 1), state);
                        if (reader.NodeType == XmlNodeType.Element &&
                            lineInfo.LineNumber == lastTag.Key &&
                            lineInfo.LinePosition == lastTag.Value)
                        {
                            for (var i = 0; i < reader.AttributeCount; i++)
                            {
                                reader.MoveToAttribute(i);
                                keepGoing = processor.Invoke(reader, lineOffsets[lineInfo.LineNumber - 1] + lineInfo.LinePosition - 1, state);
                            }
                        }
                    }
                }
            }
            catch (XmlException)
            {
                // Do Nothing
            }

            return(state);
        }
    //[DebuggerStepThrough()]
    public static XmlState ProcessFragment(ITextSource fragment, Func<XmlReader, int, XmlState, bool> processor)
    {
      var lineOffsets = new List<int>() {0};
      var state = XmlState.Other;
      var line = 1;
      var lastTag = new KeyValuePair<int, int>(0, 0);
      var attrValueQuote = '"';

      for (var i = 0; i < fragment.TextLength; i++)
      {
        switch (fragment.GetCharAt(i))
        {
          case '\r':
            if (i + 1 < fragment.TextLength && fragment.GetCharAt(i + 1) == '\n') i++;
            line++;
            lineOffsets.Add(i + 1);
            if (state == XmlState.Tag) state = XmlState.Attribute;
            break;
          case '\n':
            line++;
            lineOffsets.Add(i + 1);
            if (state == XmlState.Tag) state = XmlState.Attribute;
            break;
          default:
            switch (state)
            {
              case XmlState.Attribute:
                if (fragment.GetCharAt(i) == '=')
                {
                  i++;
                  if (i < fragment.TextLength)
                    attrValueQuote = fragment.GetCharAt(i);
                  state = XmlState.AttributeValue;
                }
                else if (fragment.GetCharAt(i) == '>')
                {
                  state = XmlState.Other;
                }
                break;
              case XmlState.AttributeValue:
                if (fragment.GetCharAt(i) == '"' || fragment.GetCharAt(i) == '\'')
                {
                  state = XmlState.Tag;
                }
                break;
              case XmlState.CData:
                if (i + 2 < fragment.TextLength && fragment.GetCharAt(i) == ']' && fragment.GetCharAt(i + 1) == ']' && fragment.GetCharAt(i + 2) == '>')
                {
                  i += 2;
                  state = XmlState.Other;
                }
                break;
              case XmlState.Comment:
                if (i + 2 < fragment.TextLength && fragment.GetCharAt(i) == '-' && fragment.GetCharAt(i + 1) == '-' && fragment.GetCharAt(i + 2) == '>')
                {
                  i += 2;
                  state = XmlState.Other;
                }
                break;
              case XmlState.Tag:
                if (char.IsWhiteSpace(fragment.GetCharAt(i)))
                {
                  state = XmlState.Attribute;
                }
                else if (fragment.GetCharAt(i) == '>')
                {
                  state = XmlState.Other;
                }
                break;
              case XmlState.Other:
                if (fragment.GetCharAt(i) == '<')
                {
                  if (i + 3 < fragment.TextLength
                    && fragment.GetCharAt(i + 1) == '!'
                    && fragment.GetCharAt(i + 2) == '-'
                    && fragment.GetCharAt(i + 3) == '-')
                  {
                    i += 3;
                    state = XmlState.Comment;
                  }
                  else if (i + 8 < fragment.TextLength
                    && fragment.GetCharAt(i + 1) == '!'
                    && fragment.GetCharAt(i + 2) == '['
                    && fragment.GetCharAt(i + 3) == 'C'
                    && fragment.GetCharAt(i + 4) == 'D'
                    && fragment.GetCharAt(i + 5) == 'A'
                    && fragment.GetCharAt(i + 6) == 'T'
                    && fragment.GetCharAt(i + 7) == 'A'
                    && fragment.GetCharAt(i + 8) == '[')
                  {
                    i += 8;
                    state = XmlState.CData;
                  }
                  else
                  {
                    state = XmlState.Tag;
                    lastTag = new KeyValuePair<int, int>(line, i - lineOffsets.Last() + 2);
                  }
                }
                break;
            }
            break;
        }
      }

      const string __noName = "___NO_NAME___";
      const string __eof = "{`EOF`}";
      var suffix = string.Empty;

      switch (state)
      {
        case XmlState.Attribute:
          if (char.IsWhiteSpace(fragment.GetCharAt(fragment.TextLength - 1)))
          {
            state = XmlState.AttributeStart;
            suffix += ">";
          }
          else
          {
            suffix += "=\"\">";
          }
          break;
        case XmlState.AttributeValue:
          if (fragment.GetCharAt(fragment.TextLength - 1) == '=')
          {
            suffix += "''>";
          }
          else
          {
            suffix += attrValueQuote.ToString() + ">";
          }
          break;
        case XmlState.CData:
          suffix += "]]>";
          break;
        case XmlState.Comment:
          suffix += "-->";
          break;
        case XmlState.Tag:
          if (fragment.GetCharAt(fragment.TextLength - 1) == '<') suffix += __noName;
          suffix += ">";
          break;
      }
      suffix += "<!--" + __eof + "-->";

      var settings = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment };
      var textReader = new AugmentedReader(fragment.CreateReader(), suffix);
      var reader = XmlReader.Create(textReader, settings);
      var lineInfo = reader as IXmlLineInfo;

      try
      {
        bool keepGoing = true;
        while (keepGoing && reader.Read() && !(reader.NodeType == XmlNodeType.Comment && reader.Value == __eof))
        {
          if (reader.LocalName != __noName)
          {
            keepGoing = processor.Invoke(reader, lineOffsets[lineInfo.LineNumber - 1]
                                                + lineInfo.LinePosition
                                                - (reader.NodeType == XmlNodeType.Element ? 2 : 1), state);
            if (reader.NodeType == XmlNodeType.Element
              && lineInfo.LineNumber == lastTag.Key
              && lineInfo.LinePosition == lastTag.Value)
            {
              for (var i = 0; i < reader.AttributeCount; i++)
              {
                reader.MoveToAttribute(i);
                keepGoing = processor.Invoke(reader, lineOffsets[lineInfo.LineNumber - 1] + lineInfo.LinePosition - 1, state);
              }
            }
          }
        }
      }
      catch (XmlException)
      {
        // Do Nothing
      }

      return state;
    }