tohtmlstream.java
来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,886 行 · 第 1/5 页
JAVA
1,886 行
{ elemContext = elemContext.push(namespaceURI,localName,name); m_elemContext = elemContext; elemContext.m_elementDesc = elemDesc; elemContext.m_isRaw = (elemFlags & ElemDesc.RAW) != 0; } if ((elemFlags & ElemDesc.HEADELEM) != 0) { // This is the <HEAD> element, do some special processing closeStartTag(); elemContext.m_startTagOpen = false; if (!m_omitMetaTag) { if (m_doIndent) indent(); writer.write( "<META http-equiv=\"Content-Type\" content=\"text/html; charset="); String encoding = getEncoding(); String encode = Encodings.getMimeEncoding(encoding); writer.write(encode); writer.write("\">"); } } } catch (IOException e) { throw new SAXException(e); } } /** * Receive notification of the end of an element. * * * @param namespaceURI * @param localName * @param name The element type name * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. */ public final void endElement( final String namespaceURI, final String localName, final String name) throws org.xml.sax.SAXException { // deal with any pending issues if (m_cdataTagOpen) closeCDATA(); // if the element has a namespace, treat it like XML, not HTML if (null != namespaceURI && namespaceURI.length() > 0) { super.endElement(namespaceURI, localName, name); return; } try { ElemContext elemContext = m_elemContext; final ElemDesc elemDesc = elemContext.m_elementDesc; final int elemFlags = elemDesc.getFlags(); final boolean elemEmpty = (elemFlags & ElemDesc.EMPTY) != 0; // deal with any indentation issues if (m_doIndent) { final boolean isBlockElement = (elemFlags&ElemDesc.BLOCK) != 0; boolean shouldIndent = false; if (m_ispreserve) { m_ispreserve = false; } else if (m_doIndent && (!m_inBlockElem || isBlockElement)) { m_startNewLine = true; shouldIndent = true; } if (!elemContext.m_startTagOpen && shouldIndent) indent(elemContext.m_currentElemDepth - 1); m_inBlockElem = !isBlockElement; } final java.io.Writer writer = m_writer; if (!elemContext.m_startTagOpen) { writer.write("</"); writer.write(name); writer.write('>'); } else { // the start-tag open when this method was called, // so we need to process it now. if (m_tracer != null) super.fireStartElem(name); // the starting tag was still open when we received this endElement() call // so we need to process any gathered attributes NOW, before they go away. int nAttrs = m_attributes.getLength(); if (nAttrs > 0) { processAttributes(m_writer, nAttrs); // clear attributes object for re-use with next element m_attributes.clear(); } if (!elemEmpty) { // As per Dave/Paul recommendation 12/06/2000 // if (shouldIndent) // writer.write('>'); // indent(m_currentIndent); writer.write("></"); writer.write(name); writer.write('>'); } else { writer.write('>'); } } // clean up because the element has ended if ((elemFlags & ElemDesc.WHITESPACESENSITIVE) != 0) m_ispreserve = true; m_isprevtext = false; // fire off the end element event if (m_tracer != null) super.fireEndElem(name); // OPTIMIZE-EMPTY if (elemEmpty) { // a quick exit if the HTML element had no children. // This block of code can be removed if the corresponding block of code // in startElement() also labeled with "OPTIMIZE-EMPTY" is also removed m_elemContext = elemContext.m_prev; return; } // some more clean because the element has ended. if (!elemContext.m_startTagOpen) { if (m_doIndent && !m_preserves.isEmpty()) m_preserves.pop(); } m_elemContext = elemContext.m_prev;// m_isRawStack.pop(); } catch (IOException e) { throw new SAXException(e); } } /** * Process an attribute. * @param writer The writer to write the processed output to. * @param name The name of the attribute. * @param value The value of the attribute. * @param elemDesc The description of the HTML element * that has this attribute. * * @throws org.xml.sax.SAXException */ protected void processAttribute( java.io.Writer writer, String name, String value, ElemDesc elemDesc) throws IOException { writer.write(' '); if ( ((value.length() == 0) || value.equalsIgnoreCase(name)) && elemDesc != null && elemDesc.isAttrFlagSet(name, ElemDesc.ATTREMPTY)) { writer.write(name); } else { // %REVIEW% %OPT% // Two calls to single-char write may NOT // be more efficient than one to string-write... writer.write(name); writer.write("=\""); if ( elemDesc != null && elemDesc.isAttrFlagSet(name, ElemDesc.ATTRURL)) writeAttrURI(writer, value, m_specialEscapeURLs); else writeAttrString(writer, value, this.getEncoding()); writer.write('"'); } } /** * Tell if a character is an ASCII digit. */ private boolean isASCIIDigit(char c) { return (c >= '0' && c <= '9'); } /** * Make an integer into an HH hex value. * Does no checking on the size of the input, since this * is only meant to be used locally by writeAttrURI. * * @param i must be a value less than 255. * * @return should be a two character string. */ private static String makeHHString(int i) { String s = Integer.toHexString(i).toUpperCase(); if (s.length() == 1) { s = "0" + s; } return s; } /** * Dmitri Ilyin: Makes sure if the String is HH encoded sign. * @param str must be 2 characters long * * @return true or false */ private boolean isHHSign(String str) { boolean sign = true; try { char r = (char) Integer.parseInt(str, 16); } catch (NumberFormatException e) { sign = false; } return sign; } /** * Write the specified <var>string</var> after substituting non ASCII characters, * with <CODE>%HH</CODE>, where HH is the hex of the byte value. * * @param string String to convert to XML format. * @param doURLEscaping True if we should try to encode as * per http://www.ietf.org/rfc/rfc2396.txt. * * @throws org.xml.sax.SAXException if a bad surrogate pair is detected. */ public void writeAttrURI( final java.io.Writer writer, String string, boolean doURLEscaping) throws IOException { // http://www.ietf.org/rfc/rfc2396.txt says: // A URI is always in an "escaped" form, since escaping or unescaping a // completed URI might change its semantics. Normally, the only time // escape encodings can safely be made is when the URI is being created // from its component parts; each component may have its own set of // characters that are reserved, so only the mechanism responsible for // generating or interpreting that component can determine whether or // not escaping a character will change its semantics. Likewise, a URI // must be separated into its components before the escaped characters // within those components can be safely decoded. // // ...So we do our best to do limited escaping of the URL, without // causing damage. If the URL is already properly escaped, in theory, this // function should not change the string value. final int end = string.length(); if (end > m_attrBuff.length) { m_attrBuff = new char[end*2 + 1]; } string.getChars(0,end, m_attrBuff, 0); final char[] chars = m_attrBuff; int cleanStart = 0; int cleanLength = 0; char ch = 0; for (int i = 0; i < end; i++) { ch = chars[i]; if ((ch < 32) || (ch > 126)) { if (cleanLength > 0) { writer.write(chars, cleanStart, cleanLength); cleanLength = 0; } if (doURLEscaping) { // Encode UTF16 to UTF8. // Reference is Unicode, A Primer, by Tony Graham. // Page 92. // Note that Kay doesn't escape 0x20... // if(ch == 0x20) // Not sure about this... -sb // { // writer.write(ch); // } // else if (ch <= 0x7F) { writer.write('%'); writer.write(makeHHString(ch)); } else if (ch <= 0x7FF) { // Clear low 6 bits before rotate, put high 4 bits in low byte, // and set two high bits. int high = (ch >> 6) | 0xC0; int low = (ch & 0x3F) | 0x80; // First 6 bits, + high bit writer.write('%'); writer.write(makeHHString(high)); writer.write('%'); writer.write(makeHHString(low)); } else if (isUTF16Surrogate(ch)) // high surrogate { // I'm sure this can be done in 3 instructions, but I choose // to try and do it exactly like it is done in the book, at least // until we are sure this is totally clean. I don't think performance // is a big issue with this particular function, though I could be // wrong. Also, the stuff below clearly does more masking than // it needs to do. // Clear high 6 bits. int highSurrogate = ((int) ch) & 0x03FF; // Middle 4 bits (wwww) + 1 // "Note that the value of wwww from the high surrogate bit pattern // is incremented to make the uuuuu bit pattern in the scalar value // so the surrogate pair don't address the BMP." int wwww = ((highSurrogate & 0x03C0) >> 6); int uuuuu = wwww + 1; // next 4 bits int zzzz = (highSurrogate & 0x003C) >> 2; // low 2 bits int yyyyyy = ((highSurrogate & 0x0003) << 4) & 0x30; // Get low surrogate character. ch = chars[++i]; // Clear high 6 bits. int lowSurrogate = ((int) ch) & 0x03FF; // put the middle 4 bits into the bottom of yyyyyy (byte 3) yyyyyy = yyyyyy | ((lowSurrogate & 0x03C0) >> 6); // bottom 6 bits. int xxxxxx = (lowSurrogate & 0x003F); int byte1 = 0xF0 | (uuuuu >> 2); // top 3 bits of uuuuu int byte2 = 0x80 | (((uuuuu & 0x03) << 4) & 0x30) | zzzz; int byte3 = 0x80 | yyyyyy; int byte4 = 0x80 | xxxxxx; writer.write('%');
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?