private void StartTag(byte[] buf, int offset, ContentToken ct, TOK tok) { m_Depth++; int colon; string name; string prefix; Hashtable ht = new Hashtable(); m_ns.PushScope(); // if i have attributes if ((tok == TOK.START_TAG_WITH_ATTS) || (tok == TOK.EMPTY_ELEMENT_WITH_ATTS)) { int start; int end; string val; for (int i=0; i<ct.getAttributeSpecifiedCount(); i++) { start = ct.getAttributeNameStart(i); end = ct.getAttributeNameEnd(i); name = utf.GetString(buf, start, end - start); start = ct.getAttributeValueStart(i); end = ct.getAttributeValueEnd(i); //val = utf.GetString(buf, start, end - start); val = NormalizeAttributeValue(buf, start, end - start); // <foo b='&'/> // <foo b='&amp;' // TODO: if val includes &, it gets double-escaped if (name.StartsWith("xmlns:")) { colon = name.IndexOf(':'); prefix = name.Substring(colon+1); m_ns.AddNamespace(prefix, val); } else if (name == "xmlns") { m_ns.AddNamespace(string.Empty, val); } else { ht.Add(name, val); } } } name = utf.GetString(buf, offset + m_enc.MinBytesPerChar, ct.NameEnd - offset - m_enc.MinBytesPerChar); colon = name.IndexOf(':'); string ns = ""; prefix = null; if (colon > 0) { prefix = name.Substring(0, colon); name = name.Substring(colon + 1); ns = m_ns.LookupNamespace(prefix); } else { ns = m_ns.DefaultNamespace; } Element newel = ElementFactory.GetElement(prefix, name, ns); foreach (string attrname in ht.Keys) { newel.SetAttribute(attrname, (string)ht[attrname]); } if (m_root == null) { m_root = newel; //FireOnDocumentStart(m_root); if (OnStreamStart!=null) OnStreamStart(this, m_root); } else { if (current != null) current.AddChild(newel); current = newel; } }
private void EndTag(byte[] buf, int offset, ContentToken ct, TOK tok) { m_Depth--; m_ns.PopScope(); if (current == null) {// end of doc if (OnStreamEnd!=null) OnStreamEnd(this, m_root); // FireOnDocumentEnd(); return; } string name = null; if ((tok == TOK.EMPTY_ELEMENT_WITH_ATTS) || (tok == TOK.EMPTY_ELEMENT_NO_ATTS)) name = utf.GetString(buf, offset + m_enc.MinBytesPerChar, ct.NameEnd - offset - m_enc.MinBytesPerChar); else name = utf.GetString(buf, offset + m_enc.MinBytesPerChar*2, ct.NameEnd - offset - m_enc.MinBytesPerChar*2); // if (current.Name != name) // throw new Exception("Invalid end tag: " + name + // " != " + current.Name); Element parent = (Element) current.Parent; if (parent == null) { DoRaiseOnStreamElement(current); //if (OnStreamElement!=null) // OnStreamElement(this, current); //FireOnElement(current); } current = parent; }
private string NormalizeAttributeValue(byte[] buf, int offset, int length) { if (length == 0) return null; string val = null; BufferAggregate buffer = new BufferAggregate(); byte[] copy = new byte[length]; System.Buffer.BlockCopy(buf, offset, copy, 0, length); buffer.Write(copy); byte[] b = buffer.GetBuffer(); int off = 0; TOK tok = TOK.END_TAG; ContentToken ct = new ContentToken(); try { while (off < b.Length) { //tok = m_enc.tokenizeContent(b, off, b.Length, ct); tok = m_enc.tokenizeAttributeValue(b, off, b.Length, ct); switch (tok) { case TOK.ATTRIBUTE_VALUE_S: case TOK.DATA_CHARS: case TOK.DATA_NEWLINE: val += (utf.GetString(b, off, ct.TokenEnd - off)); break; case TOK.CHAR_REF: case TOK.MAGIC_ENTITY_REF: val += new string(new char[] { ct.RefChar1 }); break; case TOK.CHAR_PAIR_REF: val += new string(new char[] {ct.RefChar1, ct.RefChar2}); break; case TOK.ENTITY_REF: #if CF throw new util.NotImplementedException("Token type not implemented: " + tok); #else throw new System.NotImplementedException("Token type not implemented: " + tok); #endif } off = ct.TokenEnd; } } catch (PartialTokenException) { // ignored; } catch (ExtensibleTokenException) { // ignored; } catch (Exception ex) { if (OnStreamError != null) OnStreamError(this, ex); } finally { buffer.Clear(off); } return val; }
/// <summary> /// Put bytes into the parser. /// </summary> /// <param name="buf">The bytes to put into the parse stream</param> /// <param name="offset">Offset into buf to start at</param> /// <param name="length">Number of bytes to write</param> public void Push(byte[] buf, int offset, int length) { // or assert, really, but this is a little nicer. if (length == 0) return; // No locking is required. Read() won't get called again // until this method returns. // TODO: only do this copy if we have a partial token at the // end of parsing. byte[] copy = new byte[length]; System.Buffer.BlockCopy(buf, offset, copy, 0, length); m_buf.Write(copy); byte[] b = m_buf.GetBuffer(); int off = 0; TOK tok = TOK.END_TAG; ContentToken ct = new ContentToken(); try { while (off < b.Length) { if (m_cdata) tok = m_enc.tokenizeCdataSection(b, off, b.Length, ct); else tok = m_enc.tokenizeContent(b, off, b.Length, ct); switch (tok) { case TOK.EMPTY_ELEMENT_NO_ATTS: case TOK.EMPTY_ELEMENT_WITH_ATTS: StartTag(b, off, ct, tok); EndTag(b, off, ct, tok); break; case TOK.START_TAG_NO_ATTS: case TOK.START_TAG_WITH_ATTS: StartTag(b, off, ct, tok); break; case TOK.END_TAG: EndTag(b, off, ct, tok); break; case TOK.DATA_CHARS: case TOK.DATA_NEWLINE: AddText(utf.GetString(b, off, ct.TokenEnd - off)); break; case TOK.CHAR_REF: case TOK.MAGIC_ENTITY_REF: AddText(new string(new char[] { ct.RefChar1 })); break; case TOK.CHAR_PAIR_REF: AddText(new string(new char[] {ct.RefChar1, ct.RefChar2})); break; case TOK.COMMENT: if (current != null) { // <!-- 4 // --> 3 int start = off + 4 * m_enc.MinBytesPerChar; int end = ct.TokenEnd - off - 7 * m_enc.MinBytesPerChar; string text = utf.GetString(b, start, end); current.AddChild(new Comment(text)); } break; case TOK.CDATA_SECT_OPEN: m_cdata = true; break; case TOK.CDATA_SECT_CLOSE: m_cdata = false; break; case TOK.XML_DECL: // thou shalt use UTF8, and XML version 1. // i shall ignore evidence to the contrary... // TODO: Throw an exception if these assuptions are // wrong break; case TOK.ENTITY_REF: case TOK.PI: #if CF throw new util.NotImplementedException("Token type not implemented: " + tok); #else throw new System.NotImplementedException("Token type not implemented: " + tok); #endif } off = ct.TokenEnd; } } catch (PartialTokenException) { // ignored; } catch (ExtensibleTokenException) { // ignored; } catch (Exception ex) { if (OnStreamError != null) OnStreamError(this, ex); } finally { m_buf.Clear(off); } }