Re: r6168 - in branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml: . internal

Mike Schrag <[email protected]>
Newsgroups gmane.comp.web.webobjects.woproject.devel
Message-ID <[email protected]>
blerg ... i obviously accidentally hit cmd-shift-f on FuzzyXMLParser. oh well.

On Oct 3, 2010, at 5:16 PM, [email protected] wrote:

> Author: mschrag
> Date: 2010-10-03 21:16:16 +0000 (Sun, 03 Oct 2010)
> New Revision: 6168
> 
> Modified:
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLAttribute.java
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLElement.java
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLNode.java
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLParser.java
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/AbstractFuzzyXMLNode.java
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLAttributeImpl.java
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLElementImpl.java
>   branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLFormatComposite.java
> Log:
> better support <div id="<webobject name="NestedTag"/>"> in both parsing and formatting ... add the concept of "synthetic tags" that don't structurally render
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLAttribute.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLAttribute.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLAttribute.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -38,4 +38,8 @@
> 	public void setEscape(boolean escape);
> 	
> 	public boolean isEscape();
> +	
> +	public void setHasNestedTag(boolean hasNestedTag);
> +	
> +	public boolean hasNestedTag();
> }
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLElement.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLElement.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLElement.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -71,4 +71,6 @@
> 	public boolean isSelfClosing();
> 
>   public boolean isForbiddenFromHavingChildren();
> +  
> +  public void setSynthetic(boolean synthetic);
> }
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLNode.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLNode.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLNode.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -21,5 +21,6 @@
>   public String toXMLString(RenderContext renderContext);
> 
>   public void toXMLString(RenderContext renderContext, StringBuffer xmlBuffer);
> -
> +  
> +  public boolean isSynthetic();
> }
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLParser.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLParser.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/FuzzyXMLParser.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -32,945 +32,964 @@
> 
> public class FuzzyXMLParser {
> 
> -  private Stack<FuzzyXMLNode> _stack = new Stack<FuzzyXMLNode>();
> -  private String _originalSource;
> -  private List<FuzzyXMLNode> _roots;
> -  private FuzzyXMLDocType _docType;
> +	private Stack<FuzzyXMLNode> _stack = new Stack<FuzzyXMLNode>();
> +	private String _originalSource;
> +	private List<FuzzyXMLNode> _roots;
> +	private FuzzyXMLDocType _docType;
> 
> -  private List<FuzzyXMLErrorListener> _listeners = new ArrayList<FuzzyXMLErrorListener>();
> -  private List<FuzzyXMLElement> _nonCloseElements = new ArrayList<FuzzyXMLElement>();
> -  private List<String> _looseNamespaces = new ArrayList<String>();
> -  private List<String> _autocloseTags = new ArrayList<String>();
> -  private List<String> _looseTags = new ArrayList<String>();
> +	private List<FuzzyXMLErrorListener> _listeners = new ArrayList<FuzzyXMLErrorListener>();
> +	private List<FuzzyXMLElement> _nonCloseElements = new ArrayList<FuzzyXMLElement>();
> +	private List<String> _looseNamespaces = new ArrayList<String>();
> +	private List<String> _autocloseTags = new ArrayList<String>();
> +	private List<String> _looseTags = new ArrayList<String>();
> 
> -  private boolean _wellFormedRequired = false;
> -  private boolean _isHTML = false;
> +	private boolean _wellFormedRequired = false;
> +	private boolean _isHTML = false;
> 
> -  // ∞p™[∞X≠É⁄g˜p≠·≠é∆“—K\‘»
> -  private Pattern _tag = Pattern.compile("<((|/)([^<>]*))([^<]?|>)");
> -  //	private Pattern attr = Pattern.compile("([\\w:]+?)\\s*=(\"|')([^\"]*?)\\2");
> -  private Pattern _docTypeName = Pattern.compile("^<!DOCTYPE[ \r\n\t]+([\\w\\-_]*)");
> -  private Pattern _docTypePublic = Pattern.compile("PUBLIC[ \r\n\t]+\"([^\"]*)\"[ \r\n\t]*\"*([^\">]*)\"*");
> -  private Pattern _docTypeSystem = Pattern.compile("SYSTEM[ \r\n\t]+\"([^\"]*)\"");
> -  private Pattern _docTypeSubset = Pattern.compile("\\[([^\\]]*)\\]>");
> -  private Pattern _invalidStringPattern = Pattern.compile("([<>&])");
> -  private Pattern _preCloseTagPattern = Pattern.compile("<\\s*/\\s*PRE\\s*>", Pattern.CASE_INSENSITIVE);
> +	// ï¿∏pï¿∏[ï¿∏Xï¿∏É⁄gï¿∏pï¿∏ï¿∏ï¿∏é∆“ï¿∏Kï¿∏\ï¿∏ï¿∏
> +	private Pattern _tag = Pattern.compile("<((|/)([^<>]*))([^<]?|>)");
> +	// private Pattern attr =
> +	// Pattern.compile("([\\w:]+?)\\s*=(\"|')([^\"]*?)\\2");
> +	private Pattern _docTypeName = Pattern.compile("^<!DOCTYPE[ \r\n\t]+([\\w\\-_]*)");
> +	private Pattern _docTypePublic = Pattern.compile("PUBLIC[ \r\n\t]+\"([^\"]*)\"[ \r\n\t]*\"*([^\">]*)\"*");
> +	private Pattern _docTypeSystem = Pattern.compile("SYSTEM[ \r\n\t]+\"([^\"]*)\"");
> +	private Pattern _docTypeSubset = Pattern.compile("\\[([^\\]]*)\\]>");
> +	private Pattern _invalidStringPattern = Pattern.compile("([<>&])");
> +	private Pattern _preCloseTagPattern = Pattern.compile("<\\s*/\\s*PRE\\s*>", Pattern.CASE_INSENSITIVE);
> 
> -  public FuzzyXMLParser(boolean wellFormedRequired) {
> -    this(wellFormedRequired, false);
> -  }
> +	public FuzzyXMLParser(boolean wellFormedRequired) {
> +		this(wellFormedRequired, false);
> +	}
> 
> -  public FuzzyXMLParser(boolean wellFormedRequired, boolean isHTML) {
> -    super();
> -    _wellFormedRequired = wellFormedRequired;
> -    _roots = new LinkedList<FuzzyXMLNode>();
> -    _isHTML = isHTML;
> -    // MS: Hardcoded that "wo" is a loose namespace
> -    addLooseNamespace("wo");
> -    addLooseNamespace("webobject");
> -    addLooseNamespace("webobjects");
> -    if (!_wellFormedRequired) {
> -      addAutocloseTag("img");
> -      addAutocloseTag("br");
> -      addAutocloseTag("hr");
> -      addAutocloseTag("meta");
> -      addAutocloseTag("link");
> -      addAutocloseTag("input");
> -      addAutocloseTag("spacer");
> -      addAutocloseTag("frame");
> -      addAutocloseTag("basefont");
> -      addAutocloseTag("base");
> -      addAutocloseTag("area");
> -      addAutocloseTag("col");
> -      addAutocloseTag("isindex");
> -      addAutocloseTag("param");
> -      addLooseTag("p");
> -      addLooseTag("li");
> -    }
> -  }
> -  
> -  /**
> -   * An autoclose tag is like br or link where it commonly does not have a closing tag
> -   * but it also never has contents.
> -   * 
> -   * @param autocloseTag the name of the tag to make loose
> -   */
> -  public void addAutocloseTag(String autocloseTag) {
> -    _autocloseTags.add(autocloseTag);
> -    addLooseTag(autocloseTag);
> -  }
> -  
> -  /**
> -   * A "loose" tag is like li or p where people lazily often do not close them properly,
> -   * but they may have content.
> -   * 
> -   * @param looseTag the name of the tag to make loose
> -   */
> -  public void addLooseTag(String looseTag) {
> -    _looseTags.add(looseTag);
> -  }
> +	public FuzzyXMLParser(boolean wellFormedRequired, boolean isHTML) {
> +		super();
> +		_wellFormedRequired = wellFormedRequired;
> +		_roots = new LinkedList<FuzzyXMLNode>();
> +		_isHTML = isHTML;
> +		// MS: Hardcoded that "wo" is a loose namespace
> +		addLooseNamespace("wo");
> +		addLooseNamespace("webobject");
> +		addLooseNamespace("webobjects");
> +		if (!_wellFormedRequired) {
> +			addAutocloseTag("img");
> +			addAutocloseTag("br");
> +			addAutocloseTag("hr");
> +			addAutocloseTag("meta");
> +			addAutocloseTag("link");
> +			addAutocloseTag("input");
> +			addAutocloseTag("spacer");
> +			addAutocloseTag("frame");
> +			addAutocloseTag("basefont");
> +			addAutocloseTag("base");
> +			addAutocloseTag("area");
> +			addAutocloseTag("col");
> +			addAutocloseTag("isindex");
> +			addAutocloseTag("param");
> +			addLooseTag("p");
> +			addLooseTag("li");
> +		}
> +	}
> 
> -  /**
> -   * A "loose" namespace is like the wo: namespace.  We don't actually require that
> -   * wo:if have a corresponding wo:if close tag -- it actually just needs a 
> -   * wo close tag.
> -   * 
> -   * @param namespace the name of the namespace to make loose
> -   */
> -  public void addLooseNamespace(String namespace) {
> -    _looseNamespaces.add(namespace);
> -  }
> +	/**
> +	 * An autoclose tag is like br or link where it commonly does not have a
> +	 * closing tag
> +	 * but it also never has contents.
> +	 * 
> +	 * @param autocloseTag
> +	 *          the name of the tag to make loose
> +	 */
> +	public void addAutocloseTag(String autocloseTag) {
> +		_autocloseTags.add(autocloseTag);
> +		addLooseTag(autocloseTag);
> +	}
> 
> -  /**
> -   * ∞G∞≈™[∞n∞„∞h∞…∞„∞O˜p≠Ì∞…∞X∞i≠›‚Ç≈Á≠µ≠Ü≠·™B
> -   * 
> -   * @param listener ∞…∞X∞i
> -   */
> -  public void addErrorListener(FuzzyXMLErrorListener listener) {
> -    _listeners.add(listener);
> -  }
> +	/**
> +	 * A "loose" tag is like li or p where people lazily often do not close them
> +	 * properly,
> +	 * but they may have content.
> +	 * 
> +	 * @param looseTag
> +	 *          the name of the tag to make loose
> +	 */
> +	public void addLooseTag(String looseTag) {
> +		_looseTags.add(looseTag);
> +	}
> 
> -  private void fireErrorEvent(int offset, int length, String message, FuzzyXMLNode node) {
> -    FuzzyXMLErrorEvent evt = new FuzzyXMLErrorEvent(offset, length, message, node);
> -    for (FuzzyXMLErrorListener listener : _listeners) {
> -      listener.error(evt);
> -    }
> -  }
> +	/**
> +	 * A "loose" namespace is like the wo: namespace. We don't actually require
> +	 * that
> +	 * wo:if have a corresponding wo:if close tag -- it actually just needs a
> +	 * wo close tag.
> +	 * 
> +	 * @param namespace
> +	 *          the name of the namespace to make loose
> +	 */
> +	public void addLooseNamespace(String namespace) {
> +		_looseNamespaces.add(namespace);
> +	}
> 
> -  /**
> -   * „ü˜Í∞X∞g∞…™[∞•≠©≠çXML∞h∞L∞∑∞™∞„∞g≠›∞p™[∞X≠µ≠Ü≠·™B
> -   * ¶⁄˚∞R™[∞h≠ÍXML∆é‘≤≠É≠µ≠∏≠ª≠Á≠ĉ»Ê≠“≠ê≠Ü≠·™B
> -   * 
> -   * @param in „ü˜Í∞X∞g∞…™[∞•
> -   * @return ∞p™[∞X‘—≈Ê
> -   * @throws IOException
> -   */
> -  public FuzzyXMLDocument parse(InputStream in) throws IOException {
> -    byte[] bytes = FuzzyXMLUtil.readStream(in);
> -    String encode = FuzzyXMLUtil.getEncoding(bytes);
> -    if (encode == null) {
> -      return parse(new String(bytes));
> -    }
> -    return parse(new String(bytes, encode));
> -  }
> +	/**
> +	 * ï¿∏Gï¿∏ï¿∏ï¿∏[ï¿∏nï¿∏ï¿∏ï¿∏hï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Oï¿∏pï¿∏Ì∞ï¿∏ï¿∏Xï¿∏iï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +	 * 
> +	 * @param listener
> +	 *          ï¿∏ï¿∏ï¿∏Xï¿∏i
> +	 */
> +	public void addErrorListener(FuzzyXMLErrorListener listener) {
> +		_listeners.add(listener);
> +	}
> 
> -  /**
> -   * ∞t∞@∞C∞—≠©≠çXML∞h∞L∞∑∞™∞„∞g≠›∞p™[∞X≠µ≠Ü≠·™B
> -   * ¶⁄˚∞R™[∞h≠ÍXML∆é‘≤≠É≠µ≠∏≠ª≠Á≠ĉ»Ê≠“≠ê≠Ü≠·™B
> -   * 
> -   * @param file ∞t∞@∞C∞—
> -   * @return ∞p™[∞X‘—≈Ê
> -   * @throws IOException
> -   */
> -  public FuzzyXMLDocument parse(File file) throws IOException {
> -    byte[] bytes = FuzzyXMLUtil.readStream(new FileInputStream(file));
> -    String encode = FuzzyXMLUtil.getEncoding(bytes);
> -    if (encode == null) {
> -      return parse(new String(bytes));
> -    }
> -    return parse(new String(bytes, encode));
> -  }
> +	private void fireErrorEvent(int offset, int length, String message, FuzzyXMLNode node) {
> +		FuzzyXMLErrorEvent evt = new FuzzyXMLErrorEvent(offset, length, message, node);
> +		for (FuzzyXMLErrorListener listener : _listeners) {
> +			listener.error(evt);
> +		}
> +	}
> 
> -  protected int _parse(String source, int initialOffset, boolean woOnly) {
> -    // ∞p™[∞X≠›…J⁄n
> -    Matcher matcher = _tag.matcher(source);
> -    int lastIndex = initialOffset - 1;
> -    while (matcher.find()) {
> -      int start = matcher.start() + initialOffset;
> -      int end = matcher.end() + initialOffset;
> -      if (lastIndex == -1 && start > 0) {
> -        handleText(0, start, true);
> -      }
> -      else if (lastIndex != (initialOffset - 1) && lastIndex < start) {
> -        handleText(lastIndex, start, true);
> -      }
> -      String originalText = matcher.group(1);
> -      String text = originalText.trim();
> -      // Â≠¶∞^∞O
> -      if (!woOnly && text.startsWith("%")) {
> -        // ignore
> -        handleText(start, end, false);
> -      }
> -      else if (!woOnly && text.startsWith("?")) {
> -        handleDeclaration(start, end);
> -      }
> -      else if (!woOnly && (text.startsWith("!DOCTYPE") || text.startsWith("!doctype"))) {
> -        handleDoctype(start, end, text);
> -      }
> -      else if (!woOnly && text.startsWith("![CDATA[")) {
> -        handleCDATA(start, end, _originalSource.substring(start, end));
> -      }
> -      else if (!woOnly && (text.equalsIgnoreCase("pre") || text.toLowerCase().startsWith("pre "))) {
> -        end = handlePreTag(start, end);
> -        matcher.region(end, source.length());
> -      }
> -      else if (text.startsWith("/") && (!woOnly || WodHtmlUtils.isWOTag(text.substring(1)))) {
> -        handleCloseTag(start, end, text);
> -      }
> -      else if (text.endsWith("/") && (!woOnly || WodHtmlUtils.isWOTag(text))) {
> -        if (originalText.endsWith(" ")) {
> -          fireErrorEvent(start, end - start, "You can not have a space between the / and the > in your webobject tags.", null);
> -        }
> -        handleEmptyTag(start, end);
> -      }
> -      else if (!woOnly && text.startsWith("!--")) {
> -        end = _originalSource.indexOf("-->", start);
> -        if (end > 0) {
> -          end += 3;
> -        }
> -        handleComment(start, end, _originalSource.substring(start, end));
> -        matcher.region(end, source.length());
> -      }
> -      else if (!woOnly || WodHtmlUtils.isWOTag(text)) {
> -        handleStartTag(start, end);
> -      }
> -      lastIndex = end;
> -    }
> -    return lastIndex;
> -  }
> +	/**
> +	 * ï¿∏ï¿∏Í∞Xï¿∏gï¿∏ï¿∏ï¿∏[ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏XMLï¿∏hï¿∏Lï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +	 * ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Rï¿∏[ï¿∏hï¿∏ï¿∏XMLï¿∏é‘≤ï¿∏É≠ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ĉï¿∏ï¿∏Ê≠ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +	 * 
> +	 * @param in
> +	 *          ï¿∏ï¿∏Í∞Xï¿∏gï¿∏ï¿∏ï¿∏[ï¿∏ï¿∏
> +	 * @return ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏ï¿∏
> +	 * @throws IOException
> +	 */
> +	public FuzzyXMLDocument parse(InputStream in) throws IOException {
> +		byte[] bytes = FuzzyXMLUtil.readStream(in);
> +		String encode = FuzzyXMLUtil.getEncoding(bytes);
> +		if (encode == null) {
> +			return parse(new String(bytes));
> +		}
> +		return parse(new String(bytes, encode));
> +	}
> 
> -  /**
> -   * √ø∆‰≠Æ≠µ≠Ä„n≠“≠ê≠∏XML∞\™[∞X≠›∞p™[∞X≠µ≠ÄFuzzyXMLDocument∞I∞u∞W∞F∞N∞g≠›Ô—p≠µ≠Ü≠·™B
> -   * 
> -   * @param source XML∞\™[∞X
> -   * @return ∞p™[∞X‘—≈Ê≠ÌFuzzyXMLDocument∞I∞u∞W∞F∞N∞g
> -   */
> -  public FuzzyXMLDocument parse(String source) {
> -    // ∞I∞…∞W∞i∞—≠Ì∞\™[∞X≠›€Œ¶≠µ≠Ä≠¨≠–
> -    _originalSource = source;
> -    // ∞R∞™∞„∞g™ACDATA™ADOCTYPE‰ª≠›∂˛—⁄
> -    source = FuzzyXMLUtil.comment2space(source, true);
> -    source = FuzzyXMLUtil.escapeScript(source);
> -    source = FuzzyXMLUtil.scriptlet2space(source, true);
> -    source = FuzzyXMLUtil.cdata2space(source, true);
> -    source = FuzzyXMLUtil.doctype2space(source, true);
> -    source = FuzzyXMLUtil.processing2space(source, true);
> -    source = FuzzyXMLUtil.escapeString(source);
> +	/**
> +	 * ï¿∏tï¿∏@ï¿∏Cï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏XMLï¿∏hï¿∏Lï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +	 * ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Rï¿∏[ï¿∏hï¿∏ï¿∏XMLï¿∏é‘≤ï¿∏É≠ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ĉï¿∏ï¿∏Ê≠ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +	 * 
> +	 * @param file
> +	 *          ï¿∏tï¿∏@ï¿∏Cï¿∏ï¿∏
> +	 * @return ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏ï¿∏
> +	 * @throws IOException
> +	 */
> +	public FuzzyXMLDocument parse(File file) throws IOException {
> +		byte[] bytes = FuzzyXMLUtil.readStream(new FileInputStream(file));
> +		String encode = FuzzyXMLUtil.getEncoding(bytes);
> +		if (encode == null) {
> +			return parse(new String(bytes));
> +		}
> +		return parse(new String(bytes, encode));
> +	}
> 
> -    int lastIndex = _parse(source, 0, false);
> +	protected int _parse(String source, int initialOffset, boolean woOnly, boolean parseAsSynthetic) {
> +		// ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏Jï¿∏n
> +		Matcher matcher = _tag.matcher(source);
> +		int lastIndex = initialOffset - 1;
> +		while (matcher.find()) {
> +			int start = matcher.start() + initialOffset;
> +			int end = matcher.end() + initialOffset;
> +			if (lastIndex == -1 && start > 0) {
> +				handleText(0, start, true);
> +			}
> +			else if (lastIndex != (initialOffset - 1) && lastIndex < start) {
> +				handleText(lastIndex, start, true);
> +			}
> +			String originalText = matcher.group(1);
> +			String text = originalText.trim();
> +			// ï¿∏Â≠ï¿∏ï¿∏^ï¿∏O
> +			if (!woOnly && text.startsWith("%")) {
> +				// ignore
> +				handleText(start, end, false);
> +			}
> +			else if (!woOnly && text.startsWith("?")) {
> +				handleDeclaration(start, end);
> +			}
> +			else if (!woOnly && (text.startsWith("!DOCTYPE") || text.startsWith("!doctype"))) {
> +				handleDoctype(start, end, text);
> +			}
> +			else if (!woOnly && text.startsWith("![CDATA[")) {
> +				handleCDATA(start, end, _originalSource.substring(start, end));
> +			}
> +			else if (!woOnly && (text.equalsIgnoreCase("pre") || text.toLowerCase().startsWith("pre "))) {
> +				end = handlePreTag(start, end);
> +				matcher.region(end, source.length());
> +			}
> +			else if (text.startsWith("/") && (!woOnly || WodHtmlUtils.isWOTag(text.substring(1)))) {
> +				handleCloseTag(start, end, text);
> +			}
> +			else if (text.endsWith("/") && (!woOnly || WodHtmlUtils.isWOTag(text))) {
> +				if (originalText.endsWith(" ")) {
> +					fireErrorEvent(start, end - start, "You can not have a space between the / and the > in your webobject tags.", null);
> +				}
> +				handleEmptyTag(start, end, parseAsSynthetic);
> +			}
> +			else if (!woOnly && text.startsWith("!--")) {
> +				end = _originalSource.indexOf("-->", start);
> +				if (end > 0) {
> +					end += 3;
> +				}
> +				handleComment(start, end, _originalSource.substring(start, end));
> +				matcher.region(end, source.length());
> +			}
> +			else if (!woOnly || WodHtmlUtils.isWOTag(text)) {
> +				handleStartTag(start, end, parseAsSynthetic);
> +			}
> +			lastIndex = end;
> +		}
> +		return lastIndex;
> +	}
> 
> -    if (_stack.size() > 0 && _nonCloseElements.size() > 0) {
> -      FuzzyXMLElementImpl lastElement = (FuzzyXMLElementImpl) _nonCloseElements.get(_nonCloseElements.size() - 1);
> -      String lowercaseLastElementName = lastElement.getName().toLowerCase();
> -      if (!_looseTags.contains(lowercaseLastElementName)) {
> -        fireErrorEvent(lastElement.getOffset(), lastElement.getLength(), Messages.getMessage("error.noCloseTag", lastElement.getName()), null);
> -      }
> +	/**
> +	 * ï¿∏ï¿∏Æ≠ï¿∏ï¿∏Ä„nï¿∏ï¿∏ï¿∏ê≠∏XMLï¿∏\ï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏ï¿∏FuzzyXMLDocumentï¿∏Iï¿∏uï¿∏Wï¿∏Fï¿∏Nï¿∏gï¿∏ï¿∏Ô—pï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +	 * 
> +	 * @param source
> +	 *          XMLï¿∏\ï¿∏[ï¿∏X
> +	 * @return ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏Ê≠ï¿∏FuzzyXMLDocumentï¿∏Iï¿∏uï¿∏Wï¿∏Fï¿∏Nï¿∏g
> +	 */
> +	public FuzzyXMLDocument parse(String source) {
> +		// ï¿∏Iï¿∏ï¿∏ï¿∏Wï¿∏iï¿∏ï¿∏ï¿∏Ì∞\ï¿∏[ï¿∏Xï¿∏ï¿∏€Œï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏
> +		_originalSource = source;
> +		// ï¿∏Rï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ACDATAï¿∏ADOCTYPEï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏
> +		source = FuzzyXMLUtil.comment2space(source, true);
> +		source = FuzzyXMLUtil.escapeScript(source);
> +		source = FuzzyXMLUtil.scriptlet2space(source, true);
> +		source = FuzzyXMLUtil.cdata2space(source, true);
> +		source = FuzzyXMLUtil.doctype2space(source, true);
> +		source = FuzzyXMLUtil.processing2space(source, true);
> +		source = FuzzyXMLUtil.escapeString(source);
> 
> -      for (FuzzyXMLNode openNode : _stack) {
> -        if (openNode instanceof FuzzyXMLElementImpl) {
> -          FuzzyXMLElementImpl openElement = (FuzzyXMLElementImpl) openNode;
> -          openElement.setLength(lastIndex - openElement.getOffset());
> -          if (openElement.getParentNode() == null) {
> -            _roots.add(openElement);
> -          }
> -          else {
> -            ((FuzzyXMLElementImpl) openElement.getParentNode()).appendChildWithNoCheck(openElement);
> -          }
> -        }
> -      }
> -    }
> +		int lastIndex = _parse(source, 0, false, false);
> 
> -    // MS: Capture trailing text that isn't inside of a tag at all
> -    if (lastIndex != source.length()) {
> -      handleText(Math.max(0, lastIndex), source.length(), true);
> -    }
> +		if (_stack.size() > 0 && _nonCloseElements.size() > 0) {
> +			FuzzyXMLElementImpl lastElement = (FuzzyXMLElementImpl) _nonCloseElements.get(_nonCloseElements.size() - 1);
> +			String lowercaseLastElementName = lastElement.getName().toLowerCase();
> +			if (!_looseTags.contains(lowercaseLastElementName)) {
> +				fireErrorEvent(lastElement.getOffset(), lastElement.getLength(), Messages.getMessage("error.noCloseTag", lastElement.getName()), null);
> +			}
> 
> -    FuzzyXMLElement docElement = null;
> -    if (_roots.size() == 0) {
> -      docElement = new FuzzyXMLElementImpl(null, "document", 0, _originalSource.length(), 0);
> -      //docElement.appendChild(root);
> -    }
> -    else {
> -      FuzzyXMLNode firstRoot = _roots.get(0);
> -      FuzzyXMLNode lastRoot = _roots.get(_roots.size() - 1);
> -      docElement = new FuzzyXMLElementImpl(null, "document", firstRoot.getOffset(), lastRoot.getOffset() + lastRoot.getLength() - firstRoot.getOffset(), 0);
> -      for (FuzzyXMLNode root : _roots) {
> -        ((FuzzyXMLElementImpl) docElement).appendChildWithNoCheck(root);
> -      }
> -    }
> -    FuzzyXMLDocumentImpl doc = new FuzzyXMLDocumentImpl(docElement, _docType);
> -    doc.setHTML(_isHTML);
> -    return doc;
> -  }
> +			for (FuzzyXMLNode openNode : _stack) {
> +				if (openNode instanceof FuzzyXMLElementImpl) {
> +					FuzzyXMLElementImpl openElement = (FuzzyXMLElementImpl) openNode;
> +					openElement.setLength(lastIndex - openElement.getOffset());
> +					if (openElement.getParentNode() == null) {
> +						_roots.add(openElement);
> +					}
> +					else {
> +						((FuzzyXMLElementImpl) openElement.getParentNode()).appendChildWithNoCheck(openElement);
> +					}
> +				}
> +			}
> +		}
> 
> -  /** CDATA∞m™[∞h≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleCDATA(int offset, int end, String text) {
> -    closeAutocloseTags();
> -    text = text.replaceFirst("<!\\[CDATA\\[", "");
> -    text = text.replaceFirst("\\]\\]>", "");
> -    FuzzyXMLCDATAImpl cdata = new FuzzyXMLCDATAImpl(getParent(), text, offset, end - offset);
> -    if (getParent() != null) {
> -      ((FuzzyXMLElement) getParent()).appendChild(cdata);
> -    }
> -    else {
> -      _roots.add(cdata);
> -    }
> +		// MS: Capture trailing text that isn't inside of a tag at all
> +		if (lastIndex != source.length()) {
> +			handleText(Math.max(0, lastIndex), source.length(), true);
> +		}
> 
> -    _stack.push(cdata);
> -    _parse(text, offset + "<![CDATA[".length(), true);
> -    FuzzyXMLNode poppedNode = _stack.pop();
> -    if (poppedNode != cdata) {
> -      _stack.push(poppedNode);
> -    }
> -  }
> -  
> -  private int handlePreTag(int offset, int end) {
> -    closeAutocloseTags();
> -    String[] content = _preCloseTagPattern.split(_originalSource.substring(end, _originalSource.length()), 2);
> -    String text = content[0];
> -    TagInfo info = parseTagContents(_originalSource.substring(offset + 1, end - 1));
> -    FuzzyXMLPreImpl preNode = new FuzzyXMLPreImpl(getParent(), text, offset, text.length());
> -    handleStartTag(preNode, info, offset, end);
> -    String preBlock = _originalSource.substring(offset, end + text.length() + 1);
> -    return _parse(preBlock, offset, true) - 1;
> -  }
> +		FuzzyXMLElement docElement = null;
> +		if (_roots.size() == 0) {
> +			docElement = new FuzzyXMLElementImpl(null, "document", 0, _originalSource.length(), 0);
> +			// docElement.appendChild(root);
> +		}
> +		else {
> +			FuzzyXMLNode firstRoot = _roots.get(0);
> +			FuzzyXMLNode lastRoot = _roots.get(_roots.size() - 1);
> +			docElement = new FuzzyXMLElementImpl(null, "document", firstRoot.getOffset(), lastRoot.getOffset() + lastRoot.getLength() - firstRoot.getOffset(), 0);
> +			for (FuzzyXMLNode root : _roots) {
> +				((FuzzyXMLElementImpl) docElement).appendChildWithNoCheck(root);
> +			}
> +		}
> +		FuzzyXMLDocumentImpl doc = new FuzzyXMLDocumentImpl(docElement, _docType);
> +		doc.setHTML(_isHTML);
> +		return doc;
> +	}
> 
> -  /** ∞e∞L∞X∞g∞m™[∞h≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleText(int offset, int end, boolean escape) {
> -    String text = _originalSource.substring(offset, end);
> -    //System.out.println("FuzzyXMLParser.handleText: '" + text + "'");
> -    closeAutocloseTags();
> -    FuzzyXMLTextImpl textNode = new FuzzyXMLTextImpl(getParent(), FuzzyXMLUtil.decode(text, _isHTML), offset, end - offset);
> -    textNode.setEscape(escape);
> -    if (getParent() != null) {
> -      ((FuzzyXMLElement) getParent()).appendChild(textNode);
> -    }
> -    else {
> -      _roots.add(textNode);
> -    }
> -  }
> +	/** CDATAï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleCDATA(int offset, int end, String text) {
> +		closeAutocloseTags();
> +		text = text.replaceFirst("<!\\[CDATA\\[", "");
> +		text = text.replaceFirst("\\]\\]>", "");
> +		FuzzyXMLCDATAImpl cdata = new FuzzyXMLCDATAImpl(getParent(), text, offset, end - offset);
> +		if (getParent() != null) {
> +			((FuzzyXMLElement) getParent()).appendChild(cdata);
> +		}
> +		else {
> +			_roots.add(cdata);
> +		}
> 
> -  /** XML∆é‘≤™i∂√˜ˇˆ∏˜ß™j≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleDeclaration(int offset, int end) {
> -    closeAutocloseTags();
> -    String text = _originalSource.substring(offset, end);
> -    text = text.replaceFirst("^<\\?", "");
> -    text = text.replaceFirst("\\?>$", "");
> -    text = text.trim();
> +		_stack.push(cdata);
> +		_parse(text, offset + "<![CDATA[".length(), true, true);
> +		FuzzyXMLNode poppedNode = _stack.pop();
> +		if (poppedNode != cdata) {
> +			_stack.push(poppedNode);
> +		}
> +	}
> 
> -    String[] dim = text.split("[ \r\n\t]+");
> -    String name = dim[0];
> -    String data = text.substring(name.length()).trim();
> +	private int handlePreTag(int offset, int end) {
> +		closeAutocloseTags();
> +		String[] content = _preCloseTagPattern.split(_originalSource.substring(end, _originalSource.length()), 2);
> +		String text = content[0];
> +		TagInfo info = parseTagContents(_originalSource.substring(offset + 1, end - 1));
> +		FuzzyXMLPreImpl preNode = new FuzzyXMLPreImpl(getParent(), text, offset, text.length());
> +		handleStartTag(preNode, info, offset, end);
> +		String preBlock = _originalSource.substring(offset, end + text.length() + 1);
> +		return _parse(preBlock, offset, true, false) - 1;
> +	}
> 
> -    FuzzyXMLProcessingInstructionImpl pi = new FuzzyXMLProcessingInstructionImpl(null, name, data, offset, end - offset);
> -    if (getParent() != null) {
> -      // ˜]‘v≠È‰ª≠›Ÿí≠é
> -      ((FuzzyXMLElement) getParent()).appendChild(pi);
> -    }
> -    else {
> -      _roots.add(pi);
> -    }
> +	/** ï¿∏eï¿∏Lï¿∏Xï¿∏gï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleText(int offset, int end, boolean escape) {
> +		String text = _originalSource.substring(offset, end);
> +		// System.out.println("FuzzyXMLParser.handleText: '" + text + "'");
> +		closeAutocloseTags();
> +		FuzzyXMLTextImpl textNode = new FuzzyXMLTextImpl(getParent(), FuzzyXMLUtil.decode(text, _isHTML), offset, end - offset);
> +		textNode.setEscape(escape);
> +		if (getParent() != null) {
> +			((FuzzyXMLElement) getParent()).appendChild(textNode);
> +		}
> +		else {
> +			_roots.add(textNode);
> +		}
> +	}
> 
> -    // XML should not have autoclosing tags
> -    if (name.startsWith("xml")) {
> -      _autocloseTags.clear();
> -    }
> -  }
> +	/** XMLï¿∏é‘≤ï¿∏iï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ß™jï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleDeclaration(int offset, int end) {
> +		closeAutocloseTags();
> +		String text = _originalSource.substring(offset, end);
> +		text = text.replaceFirst("^<\\?", "");
> +		text = text.replaceFirst("\\?>$", "");
> +		text = text.trim();
> 
> -  /** DOCTYPE∆é‘≤≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleDoctype(int offset, int end, String text) {
> -    closeAutocloseTags();
> -    if (_docType == null) {
> -      String name = "";
> -      String publicId = "";
> -      String systemId = "";
> -      String internalSubset = "";
> -      
> -      text = _originalSource.substring(offset, end);
> -      Matcher matcher = _docTypeName.matcher(text);
> -      if (matcher.find()) {
> -        name = matcher.group(1);
> -      }
> -      matcher = _docTypePublic.matcher(text);
> -      if (matcher.find()) {
> -        publicId = matcher.group(1);
> -        systemId = matcher.group(2);
> -      }
> -      else {
> -        matcher = _docTypeSystem.matcher(text);
> -        if (matcher.find()) {
> -          systemId = matcher.group(1);
> -        }
> -      }
> -      matcher = _docTypeSubset.matcher(text);
> -      if (matcher.find()) {
> -        internalSubset = matcher.group(1);
> -      }
> -      _docType = new FuzzyXMLDocTypeImpl(null, name, publicId, systemId, internalSubset, offset, end - offset);
> -    }
> -  }
> +		String[] dim = text.split("[ \r\n\t]+");
> +		String name = dim[0];
> +		String data = text.substring(name.length()).trim();
> 
> -  private void closeAutocloseTags() {
> -    if (_stack.size() > 0) {
> -      FuzzyXMLElementImpl lastOpenElement = (FuzzyXMLElementImpl)_stack.peek();
> -      String name = lastOpenElement.getName().toLowerCase();
> -      if (_autocloseTags.contains(name) || lastOpenElement.isForbiddenFromHavingChildren()) {
> -        int openTagEndOffset = lastOpenElement.getOffset() + lastOpenElement.getOpenTagLength();
> -        handleCloseTag(openTagEndOffset, openTagEndOffset, "/" + name, false);
> -      }
> -    }
> -  }
> -  
> -  /** Â≠¶∞^∞O≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleCloseTag(int offset, int end, String text) {
> -    handleCloseTag(offset, end, text, true);
> -  }
> +		FuzzyXMLProcessingInstructionImpl pi = new FuzzyXMLProcessingInstructionImpl(null, name, data, offset, end - offset);
> +		if (getParent() != null) {
> +			// ï¿∏]ï¿∏vï¿∏Èï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏
> +			((FuzzyXMLElement) getParent()).appendChild(pi);
> +		}
> +		else {
> +			_roots.add(pi);
> +		}
> 
> -  private void handleCloseTag(int offset, int end, String text, boolean showMismatchError) {
> -    if (_stack.size() == 0) {
> -      return;
> -    }
> -    String tagName = text.substring(1).trim();
> +		// XML should not have autoclosing tags
> +		if (name.startsWith("xml")) {
> +			_autocloseTags.clear();
> +		}
> +	}
> 
> -    // MS: Chuck does close tags like </webobject closing something else> 
> -    int chuckIndex = tagName.indexOf(' ');
> -    if (chuckIndex != -1) {
> -      String chuckWord = tagName.substring(0, chuckIndex);
> -      if (WodHtmlUtils.isWOTag(chuckWord)) {
> -        tagName = chuckWord;
> -      }
> -    }
> +	/** DOCTYPEï¿∏é‘≤ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleDoctype(int offset, int end, String text) {
> +		closeAutocloseTags();
> +		if (_docType == null) {
> +			String name = "";
> +			String publicId = "";
> +			String systemId = "";
> +			String internalSubset = "";
> 
> -    FuzzyXMLElementImpl lastOpenElement = (FuzzyXMLElementImpl) _stack.pop();
> -    String lowercaseLastOpenElementName = lastOpenElement.getName().toLowerCase();
> -    String lowercaseCloseTagName = tagName.toLowerCase();
> +			text = _originalSource.substring(offset, end);
> +			Matcher matcher = _docTypeName.matcher(text);
> +			if (matcher.find()) {
> +				name = matcher.group(1);
> +			}
> +			matcher = _docTypePublic.matcher(text);
> +			if (matcher.find()) {
> +				publicId = matcher.group(1);
> +				systemId = matcher.group(2);
> +			}
> +			else {
> +				matcher = _docTypeSystem.matcher(text);
> +				if (matcher.find()) {
> +					systemId = matcher.group(1);
> +				}
> +			}
> +			matcher = _docTypeSubset.matcher(text);
> +			if (matcher.find()) {
> +				internalSubset = matcher.group(1);
> +			}
> +			_docType = new FuzzyXMLDocTypeImpl(null, name, publicId, systemId, internalSubset, offset, end - offset);
> +		}
> +	}
> 
> -    boolean closeTagMatches = lowercaseLastOpenElementName.equals(lowercaseCloseTagName);
> -    // System.out.println("FuzzyXMLParser.handleCloseTag: lastOpen = " +
> -    // lowercaseLastOpenElementName + ", close = " + lowercaseCloseTagName);
> -    if (!closeTagMatches) {
> -      closeAutocloseTags();
> +	private void closeAutocloseTags() {
> +		if (_stack.size() > 0) {
> +			FuzzyXMLElementImpl lastOpenElement = (FuzzyXMLElementImpl) _stack.peek();
> +			String name = lastOpenElement.getName().toLowerCase();
> +			if (_autocloseTags.contains(name) || lastOpenElement.isForbiddenFromHavingChildren()) {
> +				int openTagEndOffset = lastOpenElement.getOffset() + lastOpenElement.getOpenTagLength();
> +				handleCloseTag(openTagEndOffset, openTagEndOffset, "/" + name, false);
> +			}
> +		}
> +	}
> 
> -      // Allow </wo> to close </wo:if>
> -      boolean looseNamespace = false;
> -      int colonIndex = lowercaseLastOpenElementName.indexOf(':');
> -      if (colonIndex != -1) {
> -        String elementNamespace = lowercaseLastOpenElementName.substring(0, colonIndex);
> -        if (lowercaseCloseTagName.equals(elementNamespace) && _looseNamespaces.contains(elementNamespace)) {
> -          tagName = lastOpenElement.getName();
> -          lowercaseCloseTagName = lowercaseLastOpenElementName;
> -          looseNamespace = true;
> -        }
> -      }
> +	/** ï¿∏Â≠ï¿∏ï¿∏^ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleCloseTag(int offset, int end, String text) {
> +		handleCloseTag(offset, end, text, true);
> +	}
> 
> -      if (!looseNamespace) {
> -        boolean looseTag = false;
> -        if (_looseTags.contains(lowercaseLastOpenElementName)) {
> -          looseTag = true;
> -        }
> +	private void handleCloseTag(int offset, int end, String text, boolean showMismatchError) {
> +		if (_stack.size() == 0) {
> +			return;
> +		}
> +		String tagName = text.substring(1).trim();
> 
> -        if (looseTag) {
> -          while (lowercaseLastOpenElementName != null && !lowercaseLastOpenElementName.equals(lowercaseCloseTagName)
> -              && _looseTags.contains(lowercaseLastOpenElementName)) {
> -            int lastOpenElementEndOffset = end;
> -            // int lastOpenElementEndOffset = lastOpenElement.getOffset() +
> -            // lastOpenElement.getLength();
> -            _stack.push(lastOpenElement);
> -            handleCloseTag(lastOpenElementEndOffset, lastOpenElementEndOffset, "/" + lastOpenElement.getName(), false);
> +		// MS: Chuck does close tags like </webobject closing something else>
> +		int chuckIndex = tagName.indexOf(' ');
> +		if (chuckIndex != -1) {
> +			String chuckWord = tagName.substring(0, chuckIndex);
> +			if (WodHtmlUtils.isWOTag(chuckWord)) {
> +				tagName = chuckWord;
> +			}
> +		}
> 
> -            /*
> -             FuzzyXMLElement looseElement = lastOpenElement;
> -             FuzzyXMLNode[] looseElementChildren = lastOpenElement.getChildren();
> -             FuzzyXMLElement looseElementParent = (FuzzyXMLElement) lastOpenElement.getParentNode();
> -             for (FuzzyXMLNode looseElementChild : looseElementChildren) {
> -             looseElement.removeChild(looseElementChild);
> -             looseElementParent.insertAfter(looseElementChild, looseElement);
> -             //((AbstractFuzzyXMLNode) looseElementChild).setOffset(looseElementChild.getOffset() + 1);
> -             }
> -             */
> +		FuzzyXMLElementImpl lastOpenElement = (FuzzyXMLElementImpl) _stack.pop();
> +		String lowercaseLastOpenElementName = lastOpenElement.getName().toLowerCase();
> +		String lowercaseCloseTagName = tagName.toLowerCase();
> 
> -            if (_stack.size() == 0) {
> -              lastOpenElement = null;
> -              lowercaseLastOpenElementName = null;
> -            }
> -            else {
> -              lastOpenElement = (FuzzyXMLElementImpl) _stack.pop();
> -              lowercaseLastOpenElementName = lastOpenElement.getName().toLowerCase();
> -            }
> -          }
> -        }
> -        else {
> -          FuzzyXMLElement matchingOpenElement = null;
> -          for (FuzzyXMLElement nonCloseElement : _nonCloseElements) {
> -            if (nonCloseElement.getName().equalsIgnoreCase(lowercaseCloseTagName)) {
> -              matchingOpenElement = nonCloseElement;
> -            }
> -          }
> -          if (matchingOpenElement == null) {
> -            if (showMismatchError) {
> -              fireErrorEvent(offset, end - offset, Messages.getMessage("error.noStartTag", tagName), null);
> -            }
> -            _stack.push(lastOpenElement);
> -            return;
> -          }
> +		boolean closeTagMatches = lowercaseLastOpenElementName.equals(lowercaseCloseTagName);
> +		// System.out.println("FuzzyXMLParser.handleCloseTag: lastOpen = " +
> +		// lowercaseLastOpenElementName + ", close = " + lowercaseCloseTagName);
> +		if (!closeTagMatches) {
> +			closeAutocloseTags();
> 
> -          //System.out.println("FuzzyXMLParser.handleCloseTag: mismatched close " + lastOpenElement.getName());
> -          if (showMismatchError) {
> -            //fireErrorEvent(offset, end - offset, "Found </" + tagName + "> before </" + lastOpenElement.getName() + ">", null);
> -            fireErrorEvent(lastOpenElement.getOffset(), lastOpenElement.getLength(), "Missing </" + lastOpenElement.getName() + "> tag", null);
> -          }
> -          _stack.push(lastOpenElement);
> -          handleCloseTag(offset, offset, "/" + lastOpenElement.getName(), false);
> -          lastOpenElement = (FuzzyXMLElementImpl) _stack.pop();
> -          lowercaseLastOpenElementName = lastOpenElement.getName().toLowerCase();
> -        }
> -        /*
> -         boolean matchesOpenElement = false;
> -         if (looseTag) {
> -         for (FuzzyXMLElement nonCloseElement : nonCloseElements) {
> -         if (nonCloseElement.getName().equalsIgnoreCase(lowercaseCloseTagName)) {
> -         matchesOpenElement = true;
> -         }
> -         }
> -         if (matchesOpenElement) {
> -         nonCloseElements.remove(lastOpenElement);
> -         }
> -         }
> +			// Allow </wo> to close </wo:if>
> +			boolean looseNamespace = false;
> +			int colonIndex = lowercaseLastOpenElementName.indexOf(':');
> +			if (colonIndex != -1) {
> +				String elementNamespace = lowercaseLastOpenElementName.substring(0, colonIndex);
> +				if (lowercaseCloseTagName.equals(elementNamespace) && _looseNamespaces.contains(elementNamespace)) {
> +					tagName = lastOpenElement.getName();
> +					lowercaseCloseTagName = lowercaseLastOpenElementName;
> +					looseNamespace = true;
> +				}
> +			}
> 
> -         if (lastOpenElement.getParentNode() != null) {
> -         ((FuzzyXMLElementImpl) lastOpenElement.getParentNode()).appendChildWithNoCheck(lastOpenElement);
> -         FuzzyXMLNode[] nodes = lastOpenElement.getChildren();
> -         for (int i = 0; i < nodes.length; i++) {
> -         ((AbstractFuzzyXMLNode) nodes[i]).setParentNode(lastOpenElement.getParentNode());
> -         lastOpenElement.removeChild(nodes[i]);
> -         ((FuzzyXMLElementImpl) lastOpenElement.getParentNode()).appendChildWithNoCheck(nodes[i]);
> -         }
> -         }
> -         else {
> -         //System.out.println(tagName + "≠Ì…J⁄n∞^∞O≠ª‘©≠Â≠©≠è≠Ü≠’≠ñ™B");
> -         fireErrorEvent(offset, end - offset, Messages.getMessage("error.noStartTag", tagName), null);
> -         }
> -         if (matchesOpenElement) {
> -         handleCloseTag(offset, end, text);
> -         }
> -         //			stack.push(element);
> -         return;
> -         */
> -      }
> -    }
> +			if (!looseNamespace) {
> +				boolean looseTag = false;
> +				if (_looseTags.contains(lowercaseLastOpenElementName)) {
> +					looseTag = true;
> +				}
> 
> -    if (lastOpenElement != null) {
> -      // —ó∞^∞O≠Ì∂êŸΩ≠Í—ó≠Ì∞e∞L∞X∞g∞m™[∞h≠›‚Ç≈Á≠µ≠Ä≠¨≠–
> -      if (lastOpenElement.getChildren().length == 0) {
> -        // MS: Hopefully this doesn't break things ... Sure wish I could read
> -        // Japanese to know what the original author said about this :)
> -        //lastOpenElement.appendChild(new FuzzyXMLTextImpl(getParent(), "", offset, 0));
> -      }
> -      lastOpenElement.setLength(end - lastOpenElement.getOffset());
> -      if (closeTagMatches) {
> -        lastOpenElement.setCloseTagOffset(offset);
> -        lastOpenElement.setCloseTagLength(end - offset - 2);
> -        lastOpenElement.setCloseNameOffset(text.indexOf(tagName));
> -      }
> -      _nonCloseElements.remove(lastOpenElement);
> -      if (lastOpenElement.getParentNode() == null) {
> -        _roots.add(lastOpenElement);
> -        for (FuzzyXMLElement error : _nonCloseElements) {
> -          //System.out.println(error.getName() + "≠ÍÂ≠¶≠Ä≠¢≠Ü≠’≠ñ™B");
> -          if (showMismatchError) {
> -            fireErrorEvent(error.getOffset(), error.getLength(), Messages.getMessage("error.noCloseTag", error.getName()), error);
> -          }
> -        }
> -      }
> -      else {
> -        ((FuzzyXMLElementImpl) lastOpenElement.getParentNode()).appendChildWithNoCheck(lastOpenElement);
> -      }
> -    }
> -  }
> +				if (looseTag) {
> +					while (lowercaseLastOpenElementName != null && !lowercaseLastOpenElementName.equals(lowercaseCloseTagName) && _looseTags.contains(lowercaseLastOpenElementName)) {
> +						int lastOpenElementEndOffset = end;
> +						// int lastOpenElementEndOffset = lastOpenElement.getOffset() +
> +						// lastOpenElement.getLength();
> +						_stack.push(lastOpenElement);
> +						handleCloseTag(lastOpenElementEndOffset, lastOpenElementEndOffset, "/" + lastOpenElement.getName(), false);
> 
> -  private void checkAttributeValue(FuzzyXMLAttribute attr) {
> -    String str = attr.getRawValue();
> -    if (str != null) {
> -      str = str.replaceAll("&[^&; \"]+;", " ");
> -      Matcher invalidStringMatcher = _invalidStringPattern.matcher(str);
> -      while (invalidStringMatcher.find()) {
> -        String invalidPart = invalidStringMatcher.group();
> -        fireErrorEvent(attr.getParentNode().getOffset() + attr.getValueDataOffset() + 1, attr.getValueDataLength(), "The character '" + invalidPart + "' must be escaped.", attr);
> -      }
> -    }
> -  }
> +						/*
> +						 * FuzzyXMLElement looseElement = lastOpenElement;
> +						 * FuzzyXMLNode[] looseElementChildren =
> +						 * lastOpenElement.getChildren();
> +						 * FuzzyXMLElement looseElementParent = (FuzzyXMLElement)
> +						 * lastOpenElement.getParentNode();
> +						 * for (FuzzyXMLNode looseElementChild : looseElementChildren) {
> +						 * looseElement.removeChild(looseElementChild);
> +						 * looseElementParent.insertAfter(looseElementChild, looseElement);
> +						 * //((AbstractFuzzyXMLNode)
> +						 * looseElementChild).setOffset(looseElementChild.getOffset() + 1);
> +						 * }
> +						 */
> 
> -  /** —ó∞^∞O≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleEmptyTag(int offset, int end) {
> -	closeAutocloseTags();
> -    TagInfo info = parseTagContents(_originalSource.substring(offset + 1, end - 1));
> -    FuzzyXMLNode parent = getParent();
> -    FuzzyXMLElementImpl element = new FuzzyXMLElementImpl(parent, info.name, offset, end - offset, info.nameOffset);
> -    if (parent == null) {
> -      _roots.add(element);
> -    }
> -    else {
> -      ((FuzzyXMLElement) parent).appendChild(element);
> -    }
> -    // Œ®∆«≠›‚Ç≈Á
> -    AttrInfo[] attrs = info.getAttrs();
> -    for (int i = 0; i < attrs.length; i++) {
> -      FuzzyXMLAttributeImpl attr = createFuzzyXMLAttribute(element, offset, attrs[i]);
> -      element.appendChild(attr);
> -    }
> +						if (_stack.size() == 0) {
> +							lastOpenElement = null;
> +							lowercaseLastOpenElementName = null;
> +						}
> +						else {
> +							lastOpenElement = (FuzzyXMLElementImpl) _stack.pop();
> +							lowercaseLastOpenElementName = lastOpenElement.getName().toLowerCase();
> +						}
> +					}
> +				}
> +				else {
> +					FuzzyXMLElement matchingOpenElement = null;
> +					for (FuzzyXMLElement nonCloseElement : _nonCloseElements) {
> +						if (nonCloseElement.getName().equalsIgnoreCase(lowercaseCloseTagName)) {
> +							matchingOpenElement = nonCloseElement;
> +						}
> +					}
> +					if (matchingOpenElement == null) {
> +						if (showMismatchError) {
> +							fireErrorEvent(offset, end - offset, Messages.getMessage("error.noStartTag", tagName), null);
> +						}
> +						_stack.push(lastOpenElement);
> +						return;
> +					}
> 
> -    FuzzyXMLElement branchNode = new FuzzyXMLElementImpl(element, "", 0, 0, 0) {
> -      @Override
> -      public void toXMLString(RenderContext renderContext, StringBuffer xmlBuffer) {
> -      }
> -    };
> +					// System.out.println("FuzzyXMLParser.handleCloseTag: mismatched close "
> +					// + lastOpenElement.getName());
> +					if (showMismatchError) {
> +						// fireErrorEvent(offset, end - offset, "Found </" + tagName +
> +						// "> before </" + lastOpenElement.getName() + ">", null);
> +						fireErrorEvent(lastOpenElement.getOffset(), lastOpenElement.getLength(), "Missing </" + lastOpenElement.getName() + "> tag", null);
> +					}
> +					_stack.push(lastOpenElement);
> +					handleCloseTag(offset, offset, "/" + lastOpenElement.getName(), false);
> +					lastOpenElement = (FuzzyXMLElementImpl) _stack.pop();
> +					lowercaseLastOpenElementName = lastOpenElement.getName().toLowerCase();
> +				}
> +				/*
> +				 * boolean matchesOpenElement = false;
> +				 * if (looseTag) {
> +				 * for (FuzzyXMLElement nonCloseElement : nonCloseElements) {
> +				 * if
> +				 * (nonCloseElement.getName().equalsIgnoreCase(lowercaseCloseTagName)) {
> +				 * matchesOpenElement = true;
> +				 * }
> +				 * }
> +				 * if (matchesOpenElement) {
> +				 * nonCloseElements.remove(lastOpenElement);
> +				 * }
> +				 * }
> +				 * 
> +				 * if (lastOpenElement.getParentNode() != null) {
> +				 * ((FuzzyXMLElementImpl)
> +				 * lastOpenElement.getParentNode()).appendChildWithNoCheck
> +				 * (lastOpenElement);
> +				 * FuzzyXMLNode[] nodes = lastOpenElement.getChildren();
> +				 * for (int i = 0; i < nodes.length; i++) {
> +				 * ((AbstractFuzzyXMLNode)
> +				 * nodes[i]).setParentNode(lastOpenElement.getParentNode());
> +				 * lastOpenElement.removeChild(nodes[i]);
> +				 * ((FuzzyXMLElementImpl)
> +				 * lastOpenElement.getParentNode()).appendChildWithNoCheck(nodes[i]);
> +				 * }
> +				 * }
> +				 * else {
> +				 * //System.out.println(tagName + "ï¿∏Ì…Jï¿∏nï¿∏^ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Â≠ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏B");
> +				 * fireErrorEvent(offset, end - offset,
> +				 * Messages.getMessage("error.noStartTag", tagName), null);
> +				 * }
> +				 * if (matchesOpenElement) {
> +				 * handleCloseTag(offset, end, text);
> +				 * }
> +				 * // stack.push(element);
> +				 * return;
> +				 */
> +			}
> +		}
> 
> -    if (!_wellFormedRequired) {
> -      element.appendChild(branchNode);
> -    }
> +		if (lastOpenElement != null) {
> +			// ï¿∏ï¿∏^ï¿∏Oï¿∏Ì∂êŸΩï¿∏Í—ï¿∏Ì∞eï¿∏Lï¿∏Xï¿∏gï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏
> +			if (lastOpenElement.getChildren().length == 0) {
> +				// MS: Hopefully this doesn't break things ... Sure wish I could read
> +				// Japanese to know what the original author said about this :)
> +				// lastOpenElement.appendChild(new FuzzyXMLTextImpl(getParent(), "",
> +				// offset, 0));
> +			}
> +			lastOpenElement.setLength(end - lastOpenElement.getOffset());
> +			if (closeTagMatches) {
> +				lastOpenElement.setCloseTagOffset(offset);
> +				lastOpenElement.setCloseTagLength(end - offset - 2);
> +				lastOpenElement.setCloseNameOffset(text.indexOf(tagName));
> +			}
> +			_nonCloseElements.remove(lastOpenElement);
> +			if (lastOpenElement.getParentNode() == null) {
> +				_roots.add(lastOpenElement);
> +				for (FuzzyXMLElement error : _nonCloseElements) {
> +					// System.out.println(error.getName() + "ï¿∏ÍÂ≠ï¿∏ï¿∏Ä≠ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏B");
> +					if (showMismatchError) {
> +						fireErrorEvent(error.getOffset(), error.getLength(), Messages.getMessage("error.noCloseTag", error.getName()), error);
> +					}
> +				}
> +			}
> +			else {
> +				((FuzzyXMLElementImpl) lastOpenElement.getParentNode()).appendChildWithNoCheck(lastOpenElement);
> +			}
> +		}
> +	}
> 
> -    for (FuzzyXMLAttribute attr : element.getAttributes()) {
> -      if (!_wellFormedRequired) {
> -        _stack.push(branchNode);
> -        _parse(attr.getValue(), element.getOffset() + attr.getValueDataOffset() + 1, true);
> -        FuzzyXMLNode poppedNode = _stack.pop();
> -        if (poppedNode != branchNode) {
> -          _stack.push(poppedNode);
> -        }
> -      }
> -      else {
> -        checkAttributeValue(attr);
> -      }
> -    }
> +	private void checkAttributeValue(FuzzyXMLAttribute attr) {
> +		String str = attr.getRawValue();
> +		if (str != null) {
> +			// MS: Don't consider nested tags for escaping ...
> +			if (attr.hasNestedTag()) {
> +				str = str.replaceAll("<[^>]*>", "");
> +			}
> 
> -    if (!_wellFormedRequired && !branchNode.hasChildren()) {
> -      element.removeChild(branchNode);
> -    }
> +			str = str.replaceAll("&[^&; \"]+;", " ");
> +			Matcher invalidStringMatcher = _invalidStringPattern.matcher(str);
> +			while (invalidStringMatcher.find()) {
> +				String invalidPart = invalidStringMatcher.group();
> +				fireErrorEvent(attr.getParentNode().getOffset() + attr.getValueDataOffset() + 1, attr.getValueDataLength(), "The character '" + invalidPart + "' must be escaped.", attr);
> +			}
> 
> -  }
> +		}
> +	}
> 
> -  /** ∞R∞™∞„∞g≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleComment(int offset, int end, String text) {
> -    closeAutocloseTags();
> -    FuzzyXMLNode parent = getParent();
> -    FuzzyXMLCommentImpl comment = new FuzzyXMLCommentImpl(parent, text, offset, end - offset);
> +	/** ï¿∏ï¿∏^ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleEmptyTag(int offset, int end, boolean synthetic) {
> +		closeAutocloseTags();
> +		TagInfo info = parseTagContents(_originalSource.substring(offset + 1, end - 1));
> +		FuzzyXMLNode parent = getParent();
> +		FuzzyXMLElementImpl element = new FuzzyXMLElementImpl(parent, info.name, offset, end - offset, info.nameOffset);
> +		if (parent == null) {
> +			_roots.add(element);
> +		}
> +		else {
> +			((FuzzyXMLElement) parent).appendChild(element);
> +		}
> +		// ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ç≈ï¿∏
> +		AttrInfo[] attrs = info.getAttrs();
> +		for (int i = 0; i < attrs.length; i++) {
> +			FuzzyXMLAttributeImpl attr = createFuzzyXMLAttribute(element, offset, attrs[i]);
> +			element.appendChild(attr);
> +		}
> 
> -    if (parent == null) {
> -      _roots.add(comment);
> -    }
> -    else {
> -      ((FuzzyXMLElement) parent).appendChild(comment);
> -    }
> -    
> -    _stack.push(comment);
> -    _parse(text.replaceFirst("<[^>]+-->$", ""), offset, true);
> -    FuzzyXMLNode poppedNode = _stack.pop();
> -    if (poppedNode != comment) {
> -      _stack.push(poppedNode);
> -    }
> -  }
> +		element.setSynthetic(synthetic);
> 
> -  /** …J⁄n∞^∞O≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleStartTag(int offset, int end) {
> -    closeAutocloseTags();
> -    String tagContents = _originalSource.substring(offset, end);
> -    // MS: If you're in the middle of typing, offset + 1 to end - 1 can put
> -    // you in an invalid state (for instance, if you just type "<" that will
> -    // overlap.
> -    if (tagContents.startsWith("<")) {
> -      tagContents = tagContents.substring(1);
> -    }
> -    if (tagContents.endsWith(">")) {
> -      tagContents = tagContents.substring(0, tagContents.length() - 1);
> -    }
> -    TagInfo info = parseTagContents(tagContents);
> -    // System.out.println("FuzzyXMLParser.handleStartTag: open " + info.name);
> -    FuzzyXMLElement element;
> -    if (info.name.equalsIgnoreCase("script")) {
> -      element = new FuzzyXMLScriptImpl(getParent(), info.name, offset, end - offset, info.nameOffset);
> -    }
> -    else if (info.name.equalsIgnoreCase("style")) {
> -      element = new FuzzyXMLStyleImpl(getParent(), info.name, offset, end - offset, info.nameOffset);
> -    }
> -    else { 
> -      element = new FuzzyXMLElementImpl(getParent(), info.name, offset, end - offset, info.nameOffset);
> -    }
> -    handleStartTag(element, info, offset, end);
> -  }
> +		checkElement(element);
> +	}
> 
> -  protected FuzzyXMLAttributeImpl createFuzzyXMLAttribute(FuzzyXMLElement element, int offset, AttrInfo attrInfo) {
> -    String namespace = null;
> -    String name = attrInfo.name;
> -    if (name != null) {
> -      int colonIndex = name.indexOf(':');
> -      if (colonIndex != -1) {
> -        namespace = name.substring(0, colonIndex);
> -        name = name.substring(colonIndex + 1);
> -      }
> -    }
> -    if (_wellFormedRequired) {
> -    	FuzzyXMLAttributeImpl attr = new FuzzyXMLAttributeImpl(element, namespace, name, FuzzyXMLUtil.decode(attrInfo.value, false), attrInfo.rawValue, attrInfo.offset + offset, attrInfo.end - attrInfo.offset + 1, attrInfo.valueOffset);
> -        attr.setQuoteCharacter(attrInfo.quote);
> -        return attr;
> -    }
> -    FuzzyXMLAttributeImpl attr = new FuzzyXMLAttributeImpl(element, namespace, name, attrInfo.value, attrInfo.rawValue, attrInfo.offset + offset, attrInfo.end - attrInfo.offset + 1, attrInfo.valueOffset);
> -    attr.setQuoteCharacter(attrInfo.quote);
> -    if (attrInfo.value.indexOf('"') >= 0 || attrInfo.value.indexOf('\'') >= 0 || attrInfo.value.indexOf('<') >= 0
> -        || attrInfo.value.indexOf('>') >= 0 || attrInfo.value.indexOf('&') >= 0) {
> -      attr.setEscape(false);
> -    }
> -    return attr;
> -  }
> -  
> -  /** …J⁄n∞^∞O≠›∂√˜ˇ≠µ≠Ü≠·™B */
> -  private void handleStartTag(FuzzyXMLElement element, TagInfo info, int offset, int end) {
> -    // Œ®∆«≠›‚Ç≈Á
> -    AttrInfo[] attrs = info.getAttrs();
> -    for (int i = 0; i < attrs.length; i++) {
> -      //			// ˆπŒO—ó…Ô≠Ì∞T∞|™[∞g
> -      //			if(attrs[i].name.startsWith("xmlns")){
> -      //				String uri    = attrs[i].value;
> -      //				String prefix = null;
> -      //				String[] dim = attrs[i].name.split(":");
> -      //				if(dim.length > 1){
> -      //					prefix = dim[1];
> -      //				}
> -      //				element.addNamespaceURI(prefix,uri);
> -      //			}
> -      element.appendChild(createFuzzyXMLAttribute(element, offset, attrs[i]));
> -    }
> -    _stack.push(element);
> -    _nonCloseElements.add(element);
> +	protected void checkElement(FuzzyXMLElement element) {
> +		for (FuzzyXMLAttribute attr : element.getAttributes()) {
> +			if (!_wellFormedRequired) {
> +				if (!WodHtmlUtils.isWOTag((FuzzyXMLElement) attr.getParentNode())) {
> +					_stack.push(attr.getParentNode());
> +					_parse(attr.getValue(), element.getOffset() + attr.getValueDataOffset() + 1, true, true);
> +					FuzzyXMLNode poppedNode = _stack.pop();
> +					if (poppedNode != attr.getParentNode()) {
> +						_stack.push(poppedNode);
> +					}
> +				}
> +			}
> +			else {
> +				checkAttributeValue(attr);
> +			}
> +		}
> +	}
> 
> -    FuzzyXMLElement branchNode = new FuzzyXMLElementImpl(element, "", 0, 0, 0) {
> -      @Override
> -      public void toXMLString(RenderContext renderContext, StringBuffer xmlBuffer) {
> -      }
> -    };
> +	/** ï¿∏Rï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleComment(int offset, int end, String text) {
> +		closeAutocloseTags();
> +		FuzzyXMLNode parent = getParent();
> +		FuzzyXMLCommentImpl comment = new FuzzyXMLCommentImpl(parent, text, offset, end - offset);
> 
> -    if (!_wellFormedRequired) {
> -      element.appendChild(branchNode);
> -    }
> +		if (parent == null) {
> +			_roots.add(comment);
> +		}
> +		else {
> +			((FuzzyXMLElement) parent).appendChild(comment);
> +		}
> 
> -    for (FuzzyXMLAttribute attr : element.getAttributes()) {
> -      if (!_wellFormedRequired) {
> -        _stack.push(branchNode);
> -        _parse(attr.getValue(), element.getOffset() + attr.getValueDataOffset() + 1, true);
> -        FuzzyXMLNode poppedNode = _stack.pop();
> -        if (poppedNode != branchNode) {
> -          _stack.push(poppedNode);
> -        }
> -      }
> -      else {
> -        checkAttributeValue(attr);
> -      }
> -    }
> +		_stack.push(comment);
> +		_parse(text.replaceFirst("<[^>]+-->$", ""), offset, true, true);
> +		FuzzyXMLNode poppedNode = _stack.pop();
> +		if (poppedNode != comment) {
> +			_stack.push(poppedNode);
> +		}
> +	}
> 
> -    if (!_wellFormedRequired && !branchNode.hasChildren()) {
> -      element.removeChild(branchNode);
> -    }
> -  }
> +	/** ï¿∏Jï¿∏nï¿∏^ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleStartTag(int offset, int end, boolean synthetic) {
> +		closeAutocloseTags();
> +		String tagContents = _originalSource.substring(offset, end);
> +		// MS: If you're in the middle of typing, offset + 1 to end - 1 can put
> +		// you in an invalid state (for instance, if you just type "<" that will
> +		// overlap.
> +		if (tagContents.startsWith("<")) {
> +			tagContents = tagContents.substring(1);
> +		}
> +		if (tagContents.endsWith(">")) {
> +			tagContents = tagContents.substring(0, tagContents.length() - 1);
> +		}
> +		TagInfo info = parseTagContents(tagContents);
> +		// System.out.println("FuzzyXMLParser.handleStartTag: open " + info.name);
> +		FuzzyXMLElement element;
> +		if (info.name.equalsIgnoreCase("script")) {
> +			element = new FuzzyXMLScriptImpl(getParent(), info.name, offset, end - offset, info.nameOffset);
> +		}
> +		else if (info.name.equalsIgnoreCase("style")) {
> +			element = new FuzzyXMLStyleImpl(getParent(), info.name, offset, end - offset, info.nameOffset);
> +		}
> +		else {
> +			element = new FuzzyXMLElementImpl(getParent(), info.name, offset, end - offset, info.nameOffset);
> +		}
> +		handleStartTag(element, info, offset, end);
> +		element.setSynthetic(synthetic);
> +	}
> 
> -  /** ∞X∞^∞b∞N≠ÌŸÅ‘ã≠̘vŒf≠›⁄æ„≤≠µ≠Ü≠·(∞X∞^∞b∞N≠©≠ç≠ÍŸí∂˛≠µ≠Ü≠’≠ñ)™B */
> -  private FuzzyXMLNode getParent() {
> -    if (_stack.size() == 0) {
> -      return null;
> -    }
> -    return _stack.get(_stack.size() - 1);
> -  }
> +	protected FuzzyXMLAttributeImpl createFuzzyXMLAttribute(FuzzyXMLElement element, int offset, AttrInfo attrInfo) {
> +		String namespace = null;
> +		String name = attrInfo.name;
> +		if (name != null) {
> +			int colonIndex = name.indexOf(':');
> +			if (colonIndex != -1) {
> +				namespace = name.substring(0, colonIndex);
> +				name = name.substring(colonIndex + 1);
> +			}
> +		}
> +		if (_wellFormedRequired) {
> +			FuzzyXMLAttributeImpl attr = new FuzzyXMLAttributeImpl(element, namespace, name, FuzzyXMLUtil.decode(attrInfo.value, false), attrInfo.rawValue, attrInfo.offset + offset, attrInfo.end - attrInfo.offset + 1, attrInfo.valueOffset);
> +			attr.setHasNestedTag(attrInfo.hasNestedTag);
> +			attr.setQuoteCharacter(attrInfo.quote);
> +			return attr;
> +		}
> +		FuzzyXMLAttributeImpl attr = new FuzzyXMLAttributeImpl(element, namespace, name, attrInfo.value, attrInfo.rawValue, attrInfo.offset + offset, attrInfo.end - attrInfo.offset + 1, attrInfo.valueOffset);
> +		attr.setHasNestedTag(attrInfo.hasNestedTag);
> +		attr.setQuoteCharacter(attrInfo.quote);
> +		if (attrInfo.value.indexOf('"') >= 0 || attrInfo.value.indexOf('\'') >= 0 || attrInfo.value.indexOf('<') >= 0 || attrInfo.value.indexOf('>') >= 0 || attrInfo.value.indexOf('&') >= 0) {
> +			attr.setEscape(false);
> +		}
> +		return attr;
> +	}
> 
> -  /** ∞^∞O‰ª≠›∞p™[∞X≠µ≠Ü≠·™B */
> -  private TagInfo parseTagContents(String text) {
> -    // ∞g∞…∞•
> -    Range trimmedRange = Range.trimmedRange(text);
> -    text = trimmedRange.trim(text);
> -    // Â≠¶∞^∞O≠≤≠Á≠∏≠çŸÅ‘ã≠Ì∞X∞≈∞b∞V∞∑≠›Ÿí∂˛
> -    if (text.endsWith("/")) {
> -      text = text.substring(0, text.length() - 1);
> -    }
> -    // ŸÅ∂≈≠Ì∞X∞y™[∞X≠Ü≠Å≠ª∞^∞Oˆπ
> -    TagInfo info = new TagInfo();
> -    if (FuzzyXMLUtil.getSpaceIndex(text) != -1) {
> -      info.name = text.substring(0, FuzzyXMLUtil.getSpaceIndex(text)).trim();
> -      info.nameOffset = trimmedRange.getOffset();
> -      parseAttributeContents(info, text);
> -    }
> -    else {
> -      info.name = text;
> -    }
> -    return info;
> -  }
> +	/** ï¿∏Jï¿∏nï¿∏^ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void handleStartTag(FuzzyXMLElement element, TagInfo info, int offset, int end) {
> +		// ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ç≈ï¿∏
> +		AttrInfo[] attrs = info.getAttrs();
> +		for (int i = 0; i < attrs.length; i++) {
> +			// // ï¿∏ï¿∏ï¿∏Oï¿∏ï¿∏Ô≠Ì∞Tï¿∏|ï¿∏[ï¿∏g
> +			// if(attrs[i].name.startsWith("xmlns")){
> +			// String uri = attrs[i].value;
> +			// String prefix = null;
> +			// String[] dim = attrs[i].name.split(":");
> +			// if(dim.length > 1){
> +			// prefix = dim[1];
> +			// }
> +			// element.addNamespaceURI(prefix,uri);
> +			// }
> +			element.appendChild(createFuzzyXMLAttribute(element, offset, attrs[i]));
> +		}
> +		_stack.push(element);
> +		_nonCloseElements.add(element);
> 
> -  /** ∞A∞g∞…∞r∞∑™[∞g‰ª≠›∞p™[∞X≠µ≠Ü≠·™B */
> -  private void parseAttributeContents(TagInfo info, String text) {
> +		checkElement(element);
> +	}
> 
> -    int state = 0;
> -    StringBuffer sb = new StringBuffer();
> -    String name = null;
> -    char quote = 0;
> -    int start = -1;
> -    int valueOffset = -1;
> -    boolean escape = false;
> +	/** ï¿∏Xï¿∏^ï¿∏bï¿∏Nï¿∏ÌŸÅ‘ï¿∏̘vï¿∏fï¿∏ï¿∏ï¿∏æ„≤ï¿∏ï¿∏ï¿∏Ü≠ï¿∏(ï¿∏Xï¿∏^ï¿∏bï¿∏Nï¿∏ï¿∏ï¿∏ï¿∏ÍŸí∂˛ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏)ï¿∏B */
> +	private FuzzyXMLNode getParent() {
> +		if (_stack.size() == 0) {
> +			return null;
> +		}
> +		return _stack.get(_stack.size() - 1);
> +	}
> 
> -    for (int i = 0; i < text.length(); i++) {
> -      char c = text.charAt(i);
> -      if (state == 0 && FuzzyXMLUtil.isWhitespace(c)) {
> -        state = 1;
> -      }
> -      else if (state == 1 && !FuzzyXMLUtil.isWhitespace(c)) {
> -        if (start == -1) {
> -          start = i;
> -        }
> -        state = 2;
> -        sb.append(c);
> -      }
> -      else if (state == 2) {
> -        if (c == '=') {
> -          state = 3;
> -          name = sb.toString().trim();
> -          sb.setLength(0);
> -          valueOffset = -1;
> -        }
> -        else {
> -          sb.append(c);
> -        }
> -      }
> -      else if (state == 3 && !FuzzyXMLUtil.isWhitespace(c)) {
> -        if (valueOffset == -1) {
> -          valueOffset = i;
> -        }
> -        if (c == '\'' || c == '\"') {
> -          quote = c;
> -        }
> -        else {
> -          quote = 0;
> -          sb.append(c);
> -        }
> -        state = 4;
> -      }
> -      else if (state == 4) {
> -        if (c == quote && escape == true) {
> -          sb.append(c);
> -          escape = false;
> -        }
> -        else if (c == quote || (quote == 0 && FuzzyXMLUtil.isWhitespace(c))) {
> -          // add an attribute
> -          AttrInfo attr = new AttrInfo();
> -          attr.name = FuzzyXMLUtil.decode(name, _isHTML);
> -          attr.rawValue = sb.toString();
> -          attr.value = FuzzyXMLUtil.decode(attr.rawValue, _isHTML);
> -          attr.valueOffset = valueOffset;
> -          attr.offset = start;
> -          attr.end = i + 1;
> -          attr.quote = quote;
> -          info.addAttr(attr);
> +	/** ï¿∏^ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private TagInfo parseTagContents(String text) {
> +		// ï¿∏gï¿∏ï¿∏ï¿∏ï¿∏
> +		Range trimmedRange = Range.trimmedRange(text);
> +		text = trimmedRange.trim(text);
> +		// ï¿∏Â≠ï¿∏ï¿∏^ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Å‘ï¿∏Ì∞Xï¿∏ï¿∏ï¿∏bï¿∏Vï¿∏ï¿∏ï¿∏ï¿∏ï¿∏í∂˛
> +		if (text.endsWith("/")) {
> +			text = text.substring(0, text.length() - 1);
> +		}
> +		// ï¿∏Å∂ï¿∏ï¿∏Ì∞Xï¿∏yï¿∏[ï¿∏Xï¿∏Ü≠Å≠ï¿∏ï¿∏^ï¿∏Oï¿∏ï¿∏
> +		TagInfo info = new TagInfo();
> +		if (FuzzyXMLUtil.getSpaceIndex(text) != -1) {
> +			info.name = text.substring(0, FuzzyXMLUtil.getSpaceIndex(text)).trim();
> +			info.nameOffset = trimmedRange.getOffset();
> +			parseAttributeContents(info, text);
> +		}
> +		else {
> +			info.name = text;
> +		}
> +		return info;
> +	}
> 
> -          // reset
> -          sb.setLength(0);
> -          state = 1;
> -          start = -1;
> -        }
> -        else if (c == '\\') {
> -          if (escape == true) {
> -            sb.append(c);
> -            escape = false;
> -          }
> -          else {
> -            // MS: I took out escaping .. This is potentially a really sketchy thing to do, but it
> -            // was breaking attributes like   numberformat = "\$#,##0.00"
> -            // Q: moved append to following 'else' block
> -            escape = true;
> -          }
> -        }
> -        else {
> -          if (escape) {
> -            sb.append('\\');
> -            escape = false;
> -          }
> -          sb.append(c);
> -        }
> -      }
> -    }
> -    if (state == 4 && quote == 0) {
> -      AttrInfo attr = new AttrInfo();
> -      attr.name = FuzzyXMLUtil.decode(name, _isHTML);
> -      attr.rawValue = sb.toString();
> -      attr.value = FuzzyXMLUtil.decode(attr.rawValue, _isHTML);
> -      attr.valueOffset = valueOffset;
> -      attr.offset = start;
> -      attr.end = text.length();
> -      attr.quote = quote;
> -      info.addAttr(attr);
> -    }
> -    if (state == 4 && quote != 0) {
> -      //System.out.println("FuzzyXMLParser.parseAttributeContents: " + info.name);
> -    }
> -    //		Matcher matcher = attr.matcher(text);
> -    //		while(matcher.find()){
> -    //			AttrInfo attr = new AttrInfo();
> -    //			attr.name   = matcher.group(1);
> -    //			attr.value  = FuzzyXMLUtil.decode(matcher.group(3));
> -    //			attr.offset = matcher.start();
> -    //			attr.end    = matcher.end();
> -    //			info.addAttr(attr);
> -    //		}
> -  }
> +	private static enum AttributeParseState {
> +		Start, BeforeAttributeName, InAttributeName, AfterAttributeName, InAttributeValue, InNestedTag,
> +	}
> 
> -  private class TagInfo {
> -    private String name;
> -    private int nameOffset;
> -    private ArrayList<AttrInfo> attrs = new ArrayList<AttrInfo>();
> +	/** ï¿∏Aï¿∏gï¿∏ï¿∏ï¿∏rï¿∏ï¿∏ï¿∏[ï¿∏gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B */
> +	private void parseAttributeContents(TagInfo info, String text) {
> 
> -    public void addAttr(AttrInfo attr) {
> -      // „¯≠¶≠à≠Ì≠ª≠ ≠Á≠Ä≠à‚Ç≈Á≠µ≠È≠¢
> -      AttrInfo[] info = getAttrs();
> -      for (int i = 0; i < info.length; i++) {
> -        if (info[i].name.equals(attr.name)) {
> -          return;
> -        }
> -      }
> -      attrs.add(attr);
> -    }
> +		AttributeParseState state = AttributeParseState.Start;
> +		StringBuffer tokenBuffer = new StringBuffer();
> +		String name = null;
> +		char quoteCharacter = 0;
> +		int start = -1;
> +		int valueOffset = -1;
> +		boolean escape = false;
> +		boolean hasNestedTag = false;
> 
> -    public AttrInfo[] getAttrs() {
> -      return attrs.toArray(new AttrInfo[attrs.size()]);
> -    }
> -  }
> +		for (int i = 0; i < text.length(); i++) {
> +			char c = text.charAt(i);
> +			if (state == AttributeParseState.Start && FuzzyXMLUtil.isWhitespace(c)) {
> +				state = AttributeParseState.BeforeAttributeName;
> +			}
> +			else if (state == AttributeParseState.BeforeAttributeName && !FuzzyXMLUtil.isWhitespace(c)) {
> +				if (start == -1) {
> +					start = i;
> +				}
> +				state = AttributeParseState.InAttributeName;
> +				tokenBuffer.append(c);
> +			}
> +			else if (state == AttributeParseState.InAttributeName) {
> +				if (c == '=') {
> +					state = AttributeParseState.AfterAttributeName;
> +					name = tokenBuffer.toString().trim();
> +					tokenBuffer.setLength(0);
> +					valueOffset = -1;
> +				}
> +				else {
> +					tokenBuffer.append(c);
> +				}
> +			}
> +			else if (state == AttributeParseState.AfterAttributeName && !FuzzyXMLUtil.isWhitespace(c)) {
> +				if (valueOffset == -1) {
> +					valueOffset = i;
> +				}
> +				if (c == '\'' || c == '\"') {
> +					quoteCharacter = c;
> +				}
> +				else {
> +					quoteCharacter = 0;
> +					tokenBuffer.append(c);
> +				}
> +				state = AttributeParseState.InAttributeValue;
> +			}
> +			else if (state == AttributeParseState.InAttributeValue) {
> +				if (c == quoteCharacter && escape == true) {
> +					tokenBuffer.append(c);
> +					escape = false;
> +				}
> +				else if (c == quoteCharacter || (quoteCharacter == 0 && FuzzyXMLUtil.isWhitespace(c))) {
> +					// add an attribute
> +					AttrInfo attr = new AttrInfo();
> +					attr.name = FuzzyXMLUtil.decode(name, _isHTML);
> +					attr.rawValue = tokenBuffer.toString();
> +					attr.value = FuzzyXMLUtil.decode(attr.rawValue, _isHTML);
> +					attr.valueOffset = valueOffset;
> +					attr.offset = start;
> +					attr.end = i + 1;
> +					attr.quote = quoteCharacter;
> +					attr.hasNestedTag = hasNestedTag;
> +					info.addAttr(attr);
> 
> -  private class AttrInfo {
> -    private String name;
> -    private String value;
> -    private String rawValue;
> -    private int offset;
> -    private int valueOffset;
> -    private int end;
> -    private char quote;
> -  }
> +					// reset
> +					tokenBuffer.setLength(0);
> +					state = AttributeParseState.BeforeAttributeName;
> +					start = -1;
> +					hasNestedTag = false;
> +				}
> +				else if (c == '\\') {
> +					if (escape == true) {
> +						tokenBuffer.append(c);
> +						escape = false;
> +					}
> +					else {
> +						// MS: I took out escaping .. This is potentially a really sketchy
> +						// thing to do, but it
> +						// was breaking attributes like numberformat = "\$#,##0.00"
> +						// Q: moved append to following 'else' block
> +						escape = true;
> +					}
> +				}
> +				else if (c == '<') {
> +					hasNestedTag = true;
> +					state = AttributeParseState.InNestedTag;
> +					tokenBuffer.append(c);
> +				}
> +				else {
> +					if (escape) {
> +						tokenBuffer.append('\\');
> +						escape = false;
> +					}
> +					tokenBuffer.append(c);
> +				}
> +			}
> +			else if (state == AttributeParseState.InNestedTag) {
> +				tokenBuffer.append(c);
> +				if (c == '>') {
> +					state = AttributeParseState.InAttributeValue;
> +				}
> +			}
> +		}
> +		if ((state == AttributeParseState.InAttributeValue || state == AttributeParseState.InNestedTag) && quoteCharacter == 0) {
> +			AttrInfo attr = new AttrInfo();
> +			attr.name = FuzzyXMLUtil.decode(name, _isHTML);
> +			attr.rawValue = tokenBuffer.toString();
> +			attr.value = FuzzyXMLUtil.decode(attr.rawValue, _isHTML);
> +			attr.valueOffset = valueOffset;
> +			attr.offset = start;
> +			attr.end = text.length();
> +			attr.quote = quoteCharacter;
> +			attr.hasNestedTag = hasNestedTag;
> +			info.addAttr(attr);
> +		}
> +		if (state == AttributeParseState.InAttributeValue && quoteCharacter != 0) {
> +			// System.out.println("FuzzyXMLParser.parseAttributeContents: " +
> +			// info.name);
> +		}
> +		// Matcher matcher = attr.matcher(text);
> +		// while(matcher.find()){
> +		// AttrInfo attr = new AttrInfo();
> +		// attr.name = matcher.group(1);
> +		// attr.value = FuzzyXMLUtil.decode(matcher.group(3));
> +		// attr.offset = matcher.start();
> +		// attr.end = matcher.end();
> +		// info.addAttr(attr);
> +		// }
> +	}
> 
> -  public static class Range {
> -    private int _offset;
> -    private int _length;
> +	private class TagInfo {
> +		private String name;
> +		private int nameOffset;
> +		private ArrayList<AttrInfo> attrs = new ArrayList<AttrInfo>();
> 
> -    public Range() {
> -    }
> +		public void addAttr(AttrInfo attr) {
> +			// ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ì≠ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏
> +			AttrInfo[] info = getAttrs();
> +			for (int i = 0; i < info.length; i++) {
> +				if (info[i].name.equals(attr.name)) {
> +					return;
> +				}
> +			}
> +			attrs.add(attr);
> +		}
> 
> -    public int getOffset() {
> -      return _offset;
> -    }
> +		public AttrInfo[] getAttrs() {
> +			return attrs.toArray(new AttrInfo[attrs.size()]);
> +		}
> +	}
> 
> -    public int getLength() {
> -      return _length;
> -    }
> +	private class AttrInfo {
> +		private String name;
> +		private String value;
> +		private String rawValue;
> +		private int offset;
> +		private int valueOffset;
> +		private int end;
> +		private char quote;
> +		private boolean hasNestedTag;
> +	}
> 
> -    public String trim(String str) {
> -      return str.substring(_offset, _offset + _length);
> -    }
> +	public static class Range {
> +		private int _offset;
> +		private int _length;
> 
> -    public static Range trimmedRange(String str) {
> -      int i = 0;
> -      int length = str.length();
> -      Range r = new Range();
> -      for (i = 0; i < length && str.charAt(i) <= ' '; i++) {
> -        // DO NOTHING
> -      }
> -      r._offset = i;
> +		public Range() {
> +		}
> 
> -      for (i = length - 1; i > r._offset && str.charAt(i) <= ' '; i--) {
> -        // DO NOTHING
> -      }
> -      r._length = (i - r._offset + 1);
> -      return r;
> -    }
> -  }
> +		public int getOffset() {
> +			return _offset;
> +		}
> 
> +		public int getLength() {
> +			return _length;
> +		}
> +
> +		public String trim(String str) {
> +			return str.substring(_offset, _offset + _length);
> +		}
> +
> +		public static Range trimmedRange(String str) {
> +			int i = 0;
> +			int length = str.length();
> +			Range r = new Range();
> +			for (i = 0; i < length && str.charAt(i) <= ' '; i++) {
> +				// DO NOTHING
> +			}
> +			r._offset = i;
> +
> +			for (i = length - 1; i > r._offset && str.charAt(i) <= ' '; i--) {
> +				// DO NOTHING
> +			}
> +			r._length = (i - r._offset + 1);
> +			return r;
> +		}
> +	}
> +
> }
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/AbstractFuzzyXMLNode.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/AbstractFuzzyXMLNode.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/AbstractFuzzyXMLNode.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -65,14 +65,14 @@
>   }
> 
>   /**
> -   * ∞c∞…™[≠ÌŸX∆V∞C∞x∞„∞g≠›‰–≈Î≠µ≠Ü≠·™B
> +   * ï¿∏cï¿∏ï¿∏ï¿∏[ï¿∏ÌŸXï¿∏Vï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏›‰–≈Î≠ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
>    * 
>    * @param newText
>    * @param offset
>    * @param length
>    */
>   protected void fireModifyEvent(String newText, int offset, int length) {
> -    // ≠Ü≠≤∞m™[∞h≠ª∞c∞…™[≠É‚Ç≈Á≠“≠ê≠Ä≠¢≠È≠¢∂êŸΩ≠Í≠È≠É≠à≠µ≠È≠¢
> +    // ï¿∏Ü≠ï¿∏ï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏cï¿∏ï¿∏ï¿∏[ï¿∏É‚Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏È≠ï¿∏ï¿∏êŸΩï¿∏Í≠È≠É≠ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏
>     FuzzyXMLDocumentImpl doc = getDocument();
>     if (doc == null) {
>       return;
> @@ -81,14 +81,14 @@
>   }
> 
>   /**
> -   * ∞m™[∞h≠Ì√Ê‚u∂îñ≠›ŸX∆V≠µ≠Ü≠·™B∞c∞…™[≠ÌÏŸXŒO≠É‘Ä≠Ñ∂o≠µ≠Ü≠·™B
> +   * ï¿∏mï¿∏[ï¿∏hï¿∏Ì√Ê‚uï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Xï¿∏Vï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏Bï¿∏cï¿∏ï¿∏ï¿∏[ï¿∏ÌÏŸXï¿∏Oï¿∏É‘Ä≠Ñ∂oï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
>    * 
>    * @param parent
>    * @param offset
>    * @param append
>    */
>   protected void appendOffset(FuzzyXMLElement parent, int offset, int append) {
> -    // ≠Ü≠≤∞m™[∞h≠ª∞c∞…™[≠É‚Ç≈Á≠“≠ê≠Ä≠¢≠È≠¢∂êŸΩ≠Í≠È≠É≠à≠µ≠È≠¢
> +    // ï¿∏Ü≠ï¿∏ï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏cï¿∏ï¿∏ï¿∏[ï¿∏É‚Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏È≠ï¿∏ï¿∏êŸΩï¿∏Í≠È≠É≠ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏
>     FuzzyXMLDocumentImpl doc = getDocument();
>     if (doc == null) {
>       return;
> @@ -130,4 +130,8 @@
>   public boolean hasLineBreaks() {
>     return true;
>   }
> +  
> +  public boolean isSynthetic() {
> +  	return false;
> +  }
> }
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLAttributeImpl.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLAttributeImpl.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLAttributeImpl.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -15,6 +15,7 @@
>   private String _value;
>   private String _rawValue;
>   private int _valueOffset;
> +  private boolean _hasNestedTag;
> 
>   public FuzzyXMLAttributeImpl(String namespace, String name) {
>     this(null, namespace, name, null, null, -1, -1, -1);
> @@ -34,6 +35,14 @@
>     this._rawValue = rawValue;
>     _valueOffset = valueOffset;
>   }
> +  
> +  public void setHasNestedTag(boolean hasNestedTag) {
> +		_hasNestedTag = hasNestedTag;
> +	}
> +  
> +  public boolean hasNestedTag() {
> +		return _hasNestedTag;
> +	}
> 
>   public String getRawValue() {
>     return _rawValue;
> @@ -106,11 +115,11 @@
>     this._value = (value == null) ? "" : value;
>     this._rawValue = this._value;
> 
> -    // ŸX∆V∞C∞x∞„∞g≠›‰–≈Î
> +    // ï¿∏Xï¿∏Vï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏›‰–≈ï¿∏
>     FuzzyXMLDocumentImpl document = getDocument();
>     boolean html = (document == null) ? true : document.isHTML();
>     fireModifyEvent(toXMLString(new RenderContext(html)), getOffset(), getLength());
> -    // √Ê‚u∂îñ≠›ŸX∆V
> +    // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Xï¿∏V
>     appendOffset((FuzzyXMLElement) getParentNode(), getOffset(), this._value.length() - length);
>   }
> 
> @@ -191,15 +200,24 @@
>     if (quote != 0) {
>       xmlBuffer.append(quote);
>     }
> -    if (_escape) {
> +    // MS: Technically we want to escape everything BUT the nested tags, but just avoid it all for now
> +    boolean hasNestedTag = hasNestedTag();
> +    if (_escape && hasNestedTag) {
>       // Only do minimal XML escaping on the contents of attribute values
>       xmlBuffer.append(FuzzyXMLUtil.escape(_value, false));
>     }
>     else {
> +    	boolean inNestedTag = false;
>       String value = getValue();
>       for (int i = 0; i < value.length(); i++) {
>         char c = value.charAt(i);
> -        if (_quote == c) {
> +        if (hasNestedTag && c == '<') {
> +        	inNestedTag = true;
> +        }
> +        else if (c == '>') {
> +        	inNestedTag = false;
> +        }
> +        else if (!inNestedTag && _quote == c) {
>           xmlBuffer.append('\\');
>         }
>         xmlBuffer.append(c);
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLElementImpl.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLElementImpl.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLElementImpl.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -37,6 +37,8 @@
>   private int _closeNameOffset;
> 
>   private Boolean _isNonBreaking;
> +  
> +  private boolean _synthetic;
> 
>   //	private HashMap namespace = new HashMap();
> 
> @@ -102,24 +104,24 @@
>   }
> 
>   /**
> -   * XML≠Ì‚f‹∞e∞L∞X∞g≠©≠ç⁄q∞m™[∞h‘Q≠›‚Ç≈Á≠µ≠Ü≠·™B
> +   * XMLï¿∏Ì‚fï¿∏‹∞eï¿∏Lï¿∏Xï¿∏gï¿∏ï¿∏ï¿∏ï¿∏qï¿∏mï¿∏[ï¿∏hï¿∏Qï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
>    * <p>
> -   * ‚Ê∂í≠Ì<code>appendChild()</code>≠Å⁄q∞m™[∞h≠›‚Ç≈Á≠µ≠∏∂êŸΩ™A
> -   * ∞…∞X∞i≠É≠Í<code>FuzzyXMLNode#toXMLString()</code>≠Ì‘—≈Ê≠ª∆V≠µ≠¢∞e∞L∞X∞g≠Æ≠µ≠Ăʂm≠“≠ê≠Ü≠·≠ª™A
> -   * ≠±≠Ì∞™∞\∞b∞h≠›˜p≠¢≠Ä⁄q∞m™[∞h≠›‚Ç≈Á≠µ≠∏∂êŸΩ™A√ø∆‰≠Å„n≠µ≠∏∞e∞L∞X∞g≠ª∆V≠µ≠¢∞e∞L∞X∞g≠Æ≠µ≠Ä„n≠“≠ê≠Ü≠·™B
> -   * s∆“≠ÈXML≠›∞p™[∞X≠µ™A‘“≠Ì∞e∞L∞X∞g∂îñ≠›€⁄ˇ≠·≠éK˜v≠ª≠ ≠é∂êŸΩ≠É⁄g˜p≠µ≠Ä≠–≠≤≠“≠¢™B
> +   * ï¿∏Ê∂ï¿∏ï¿∏<code>appendChild()</code>ï¿∏Å⁄qï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏êŸΩï¿∏A
> +   * ï¿∏ï¿∏ï¿∏Xï¿∏iï¿∏É≠ï¿∏<code>FuzzyXMLNode#toXMLString()</code>ï¿∏Ì‘ï¿∏ï¿∏Ê≠ï¿∏ï¿∏Vï¿∏ï¿∏ï¿∏ï¿∏ï¿∏eï¿∏Lï¿∏Xï¿∏gï¿∏Æ≠ï¿∏ï¿∏Ăʂmï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏ï¿∏A
> +   * ï¿∏ï¿∏ï¿∏Ì∞ï¿∏ï¿∏\ï¿∏bï¿∏hï¿∏ï¿∏pï¿∏ï¿∏ï¿∏Ä⁄qï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏êŸΩï¿∏Aï¿∏ï¿∏Å„nï¿∏ï¿∏ï¿∏ï¿∏ï¿∏eï¿∏Lï¿∏Xï¿∏gï¿∏ï¿∏ï¿∏Vï¿∏ï¿∏ï¿∏ï¿∏ï¿∏eï¿∏Lï¿∏Xï¿∏gï¿∏Æ≠ï¿∏ï¿∏Ä„nï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +   * ï¿∏sï¿∏ï¿∏ï¿∏ï¿∏XMLï¿∏ï¿∏ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏Aï¿∏ï¿∏ï¿∏Ì∞eï¿∏Lï¿∏Xï¿∏gï¿∏ï¿∏ï¿∏ï¿∏€⁄ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Kï¿∏vï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏êŸΩï¿∏É⁄gï¿∏pï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏B
>    * </p>
> -   * @param text ‚Ç≈Á≠·≠é⁄q˜vŒf≠›…Ü≠ñ≠≤XML≠Ì‚f‹™B
> +   * @param text ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏qï¿∏vï¿∏fï¿∏ï¿∏ï¿∏Ü≠ï¿∏XMLï¿∏Ì‚fï¿∏‹™B
>    */
>   public void appendChildrenFromText(String text, boolean wo54) {
>     if (text.length() == 0) {
>       return;
>     }
> -    // √ê„x∞G∞‘∞™∞„∞g≠›Œ}„ü≠µ≠Ä∞I∞t∞Z∞b∞g≠›⁄æ„≤
> +    // ï¿∏ï¿∏xï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏}ï¿∏ï¿∏Ä∞Iï¿∏tï¿∏Zï¿∏bï¿∏gï¿∏ï¿∏ï¿∏æ„≤
>     FuzzyXMLElement test = new FuzzyXMLElementImpl("test");
>     appendChild(test);
>     int offset = test.getOffset();
> -    // ∞I∞t∞Z∞b∞g≠›⁄æ„≤≠µ≠∏≠ç≠·≠®Ÿí∂˛
> +    // ï¿∏Iï¿∏tï¿∏Zï¿∏bï¿∏gï¿∏ï¿∏ï¿∏æ„≤ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ç≠·ï¿∏ï¿∏ï¿∏í∂˛
>     removeChild(test);
> 
>     String parseText = "<root>" + text + "</root>";
> @@ -139,48 +141,48 @@
>   }
> 
>   /**
> -   * ≠±≠Ì∞G∞‘∞™∞„∞g≠É⁄q∞m™[∞h≠›‚Ç≈Á≠µ≠Ü≠·™B
> -   * √È≈º≠Ì∂êŸΩ≠Í∞m™[∞h≠›‚Ç≈Á≠·≠é≠±≠Æ≠Í≠Å≠«≠Ü≠’≠ñ™iFuzzyXMLException≠ª‰–∆¶≠µ≠Ü≠·™j™B
> +   * ï¿∏ï¿∏ï¿∏Ì∞Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏É⁄qï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
> +   * ï¿∏È≈ï¿∏ï¿∏Ì∂êŸΩï¿∏Í∞mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏é≠±ï¿∏Æ≠Í≠Å≠ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏iFuzzyXMLExceptionï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏jï¿∏B
>    * 
>    * <ul>
> -   *   <li>∞G∞‘∞™∞„∞g≠ªŒπ≠Ì∞c∞…™[≠ÉŒ®≠µ≠Ä≠¢≠é∂êŸΩ™i∆e∞G∞‘∞™∞„∞g≠©≠çremove≠·≠ê≠΂Ç≈Á≠Å≠«≠Ü≠·™j</li>
> -   *   <li>∞G∞‘∞™∞„∞g≠ª⁄q∞m™[∞h≠›⁄ˇ≠Á≠Ä≠¢≠é∂êŸΩ</li>
> +   *   <li>ï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ì∞cï¿∏ï¿∏ï¿∏[ï¿∏ÉŒï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏êŸΩï¿∏iï¿∏eï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏ï¿∏removeï¿∏ï¿∏ï¿∏ï¿∏΂Ç≈ï¿∏ï¿∏Å≠ï¿∏ï¿∏Ü≠ï¿∏ï¿∏j</li>
> +   *   <li>ï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏qï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏êŸΩ</li>
>    * </ul>
>    * 
> -   * @param node ‚Ç≈Á≠·≠é∞m™[∞h™B
> -   *   ∞G∞‘∞™∞„∞g≠Ì∂êŸΩ™A⁄q≠›⁄ˇ≠∏≠È≠¢∞G∞‘∞™∞„∞g≠›⁄w‚è≠µ≠Ä≠–≠≤≠“≠¢™B
> -   *   ≠·≠Å≠É⁄q˜vŒf≠›Ÿ\‚zŸÏ≠†≠Ì∞G∞‘∞™∞„∞g≠›„n≠·≠Æ„à‰≠Å€⁄ˇ≠µ≠Ä≠¢≠é√Ê‚u∂îñ≠ª„¯…ú≠“≠ê≠Ü≠’≠ñ™B
> +   * @param node ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏mï¿∏[ï¿∏hï¿∏B
> +   *   ï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏Ì∂êŸΩï¿∏Aï¿∏qï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏ï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏wï¿∏è≠µï¿∏Ä≠ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏B
> +   *   ï¿∏ï¿∏ï¿∏Å≠É⁄qï¿∏vï¿∏fï¿∏ï¿∏ï¿∏\ï¿∏zï¿∏Ï≠†≠Ì∞Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏nï¿∏ï¿∏ï¿∏Æ„ï¿∏ï¿∏ï¿∏ï¿∏Å€⁄ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏Ê‚uï¿∏ï¿∏ñ≠ª„ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏B
>    *   
> -   * @exception jp.aonir.fuzzyxml.FuzzyXMLException ∞m™[∞h≠›‚Ç≈Á≠Å≠«≠È≠¢∂êŸΩ
> +   * @exception jp.aonir.fuzzyxml.FuzzyXMLException ï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏Å≠ï¿∏ï¿∏È≠ï¿∏ï¿∏êŸΩ
>    */
>   public void appendChild(FuzzyXMLNode node) {
>     appendChild(node, true, true);
>   }
> 
>   /**
> -   * ∞p™[∞X⁄ı≠É<code>appendChild()</code>∞™∞\∞b∞h≠ÌŒã≠í≠è≠É⁄g˜p≠µ≠Ü≠·™B
> +   * ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏ï¿∏<code>appendChild()</code>ï¿∏ï¿∏ï¿∏\ï¿∏bï¿∏hï¿∏ÌŒï¿∏ï¿∏ï¿∏É⁄gï¿∏pï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
>    */
>   public void appendChildWithNoCheck(FuzzyXMLNode node) {
>     appendChild(node, true, false);
>   }
> 
>   /**
> -   * ≠±≠Ì∞G∞‘∞™∞„∞g≠É⁄q∞m™[∞h≠›‚Ç≈Á™B
> +   * ï¿∏ï¿∏ï¿∏Ì∞Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏É⁄qï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏B
>    * 
> -   * @param node ‚Ç≈Á≠·≠é∞m™[∞h™B
> -   *   ∞G∞‘∞™∞„∞g≠Ì∂êŸΩ™A⁄q≠›⁄ˇ≠∏≠È≠¢∞G∞‘∞™∞„∞g≠›⁄w‚è≠µ≠Ä≠–≠≤≠“≠¢™B
> -   *   ≠·≠Å≠É⁄q˜vŒf≠›Ÿ\‚zŸÏ≠†≠Ì∞G∞‘∞™∞„∞g≠›„n≠·≠Æ„à‰≠Å€⁄ˇ≠µ≠Ä≠¢≠é√Ê‚u∂îñ≠ª„¯…ú≠“≠ê≠Ü≠’≠ñ™B
> -   * @param fireEvent ∞C∞x∞„∞g≠›‰–≈Î≠·≠é≠©≠Ç≠¤≠©™B
> -   *   false≠›⁄w‚è≠µ≠∏∂êŸΩ™A∞m™[∞h≠ª⁄ˇ≠Á≠Ä≠¢≠é√Ê‚u∂îñ≠Ì„¯…ú∂√˜ˇ≠àŸs≠¢≠Ü≠’≠ñ™B
> -   * @param check ‚Ç≈Á≠·≠é∞m™[∞h≠Ì‘ƒ∂Ø≠›Ÿs≠¤≠©≠Ç≠¤≠©™B
> -   *   true≠›⁄w‚è≠µ≠∏∂êŸΩ™A√È≈º≠Ì≠É…Y„ˆ≠·≠é∂êŸΩFuzzyXMLException≠›throw≠µ≠Ü≠·™B
> +   * @param node ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏mï¿∏[ï¿∏hï¿∏B
> +   *   ï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏Ì∂êŸΩï¿∏Aï¿∏qï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏ï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏wï¿∏è≠µï¿∏Ä≠ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏B
> +   *   ï¿∏ï¿∏ï¿∏Å≠É⁄qï¿∏vï¿∏fï¿∏ï¿∏ï¿∏\ï¿∏zï¿∏Ï≠†≠Ì∞Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏nï¿∏ï¿∏ï¿∏Æ„ï¿∏ï¿∏ï¿∏ï¿∏Å€⁄ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏Ê‚uï¿∏ï¿∏ñ≠ª„ï¿∏ï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏B
> +   * @param fireEvent ï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏›‰–≈Î≠ï¿∏ï¿∏é≠©ï¿∏Ç≠ï¿∏ï¿∏ï¿∏ï¿∏B
> +   *   falseï¿∏ï¿∏ï¿∏wï¿∏è≠µï¿∏ï¿∏ï¿∏êŸΩï¿∏Aï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏Ê‚uï¿∏ï¿∏ï¿∏Ì„ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏sï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏ï¿∏B
> +   * @param check ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏mï¿∏[ï¿∏hï¿∏Ì‘ï¿∏ï¿∏Ø≠ï¿∏ï¿∏sï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ç≠ï¿∏ï¿∏ï¿∏ï¿∏B
> +   *   trueï¿∏ï¿∏ï¿∏wï¿∏è≠µï¿∏ï¿∏ï¿∏êŸΩï¿∏Aï¿∏È≈ï¿∏ï¿∏Ì≠É…Yï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏êŸΩFuzzyXMLExceptionï¿∏ï¿∏throwï¿∏ï¿∏ï¿∏Ü≠ï¿∏ï¿∏B
>    *   <ul>
> -   *     <li>∞m™[∞h≠ªŒπ≠Ì∞c∞…™[≠ÉŒ®≠µ≠Ä≠¢≠é∂êŸΩ</li>
> -   *     <li>∞G∞‘∞™∞„∞g≠ª≠·≠Å≠É⁄q—ƒ≠›⁄ˇ≠Á≠Ä≠¢≠é∂êŸΩ</li>
> +   *     <li>ï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ì∞cï¿∏ï¿∏ï¿∏[ï¿∏ÉŒï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏êŸΩ</li>
> +   *     <li>ï¿∏Gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Å≠É⁄qï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Ä≠ï¿∏ï¿∏ï¿∏êŸΩ</li>
>    *   </ul>
> -   *   ∞p™[∞X⁄ı≠È≠Ç™A‘ƒ∂Ø≠›Ÿs≠¢≠∏≠–≠È≠¢∂êŸΩ≠Ífalse≠›⁄w‚è≠µ≠Ü≠·™B
> +   *   ï¿∏pï¿∏[ï¿∏Xï¿∏ï¿∏ï¿∏È≠Ç™Aï¿∏ï¿∏ï¿∏Ø≠ï¿∏ï¿∏sï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏ï¿∏êŸΩï¿∏ï¿∏falseï¿∏ï¿∏ï¿∏wï¿∏è≠µï¿∏Ü≠ï¿∏ï¿∏B
>    *   
> -   * @exception jp.aonir.fuzzyxml.FuzzyXMLException ∞m™[∞h≠›‚Ç≈Á≠Å≠«≠È≠¢∂êŸΩ
> +   * @exception jp.aonir.fuzzyxml.FuzzyXMLException ï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏Ç≈ï¿∏ï¿∏Å≠ï¿∏ï¿∏È≠ï¿∏ï¿∏êŸΩ
>    */
>   private void appendChild(FuzzyXMLNode node, boolean fireEvent, boolean check) {
>     if (check) {
> @@ -209,7 +211,7 @@
>         _children.add(node);
>         return;
>       }
> -      // ‚Ç≈Á≠·≠é∞m™[∞h≠Ì√Ê‚u(ŸÅ‘ã)≠›‘v⁄Z
> +      // ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏mï¿∏[ï¿∏hï¿∏Ì√Ê‚u(ï¿∏Å‘ï¿∏)ï¿∏ï¿∏ï¿∏vï¿∏Z
>       FuzzyXMLNode[] nodes = getChildren();
>       int offset = 0;
>       if (nodes.length == 0) {
> @@ -219,7 +221,7 @@
>         for (int i = 0; i < attrs.length; i++) {
>           offset = offset + attrs[i].toXMLString(new RenderContext(getDocument().isHTML())).length();
>         }
> -        // ≠±≠±‰÷ˆ–™H
> +        // ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏H
>         offset = offset + 2;
> 
>         nodeImpl.setOffset(offset);
> @@ -231,10 +233,10 @@
>         String xml = toXMLString(new RenderContext(getDocument().isHTML()));
>         _children.remove(node);
> 
> -        // ∞C∞x∞„∞g≠̉–≈Î
> +        // ï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏̉ï¿∏ï¿∏ï¿∏
>         if (fireEvent) {
>           fireModifyEvent(xml, getOffset(), getLength());
> -          // √Ê‚u∂îñ≠ÌŸX∆V
> +          // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ÌŸXï¿∏V
>           appendOffset(this, offset, xml.length() - length);
>         }
> 
> @@ -245,14 +247,14 @@
>         for (int i = 0; i < nodes.length; i++) {
>           offset = nodes[i].getOffset() + nodes[i].getLength();
>         }
> -        // ∞C∞x∞„∞g≠̉–≈Î
> +        // ï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏̉ï¿∏ï¿∏ï¿∏
>         if (fireEvent) {
>           fireModifyEvent(nodeImpl.toXMLString(new RenderContext(getDocument().isHTML())), offset, 0);
> -          // √Ê‚u∂îñ≠ÌŸX∆V
> +          // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ÌŸXï¿∏V
>           appendOffset(this, offset, node.toXMLString(new RenderContext(getDocument().isHTML())).length());
>         }
> 
> -        // ŸÅ‘ã≠É‚Ç≈Á
> +        // ï¿∏Å‘ï¿∏É‚Ç≈ï¿∏
>         nodeImpl.setOffset(offset);
>         if (fireEvent) {
>           nodeImpl.setLength(node.toXMLString(new RenderContext(getDocument().isHTML())).length());
> @@ -276,7 +278,7 @@
>   }
> 
>   public FuzzyXMLNode[] getChildren() {
> -    // ∞A∞g∞…∞r∞∑™[∞g≠Í…Ü≠Ü≠È≠¢™H
> +    // ï¿∏Aï¿∏gï¿∏ï¿∏ï¿∏rï¿∏ï¿∏ï¿∏[ï¿∏gï¿∏Í…Ü≠Ü≠È≠ï¿∏ï¿∏H
>     return _children.toArray(new FuzzyXMLNode[_children.size()]);
>   }
> 
> @@ -307,11 +309,11 @@
>   }
> 
>   public void insertAfter(FuzzyXMLNode newChild, FuzzyXMLNode refChild) {
> -    // ∞A∞g∞…∞r∞∑™[∞g≠Ì∂êŸΩ≠Í≠È≠É≠à≠µ≠È≠¢
> +    // ï¿∏Aï¿∏gï¿∏ï¿∏ï¿∏rï¿∏ï¿∏ï¿∏[ï¿∏gï¿∏Ì∂êŸΩï¿∏Í≠È≠É≠ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏
>     if (newChild instanceof FuzzyXMLAttribute || refChild instanceof FuzzyXMLAttribute) {
>       return;
>     }
> -    // Œ}„ü≠·≠é√Ê‚u≠›‚T≠·
> +    // ï¿∏}ï¿∏ï¿∏ï¿∏Ê‚uï¿∏ï¿∏Tï¿∏ï¿∏
>     FuzzyXMLNode[] children = getChildren();
>     FuzzyXMLNode targetNode = null;
>     boolean flag = false;
> @@ -332,11 +334,11 @@
>   }
> 
>   public void insertBefore(FuzzyXMLNode newChild, FuzzyXMLNode refChild) {
> -    // ∞A∞g∞…∞r∞∑™[∞g≠Ì∂êŸΩ≠Í≠È≠É≠à≠µ≠È≠¢
> +    // ï¿∏Aï¿∏gï¿∏ï¿∏ï¿∏rï¿∏ï¿∏ï¿∏[ï¿∏gï¿∏Ì∂êŸΩï¿∏Í≠È≠É≠ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏
>     if (newChild instanceof FuzzyXMLAttribute || refChild instanceof FuzzyXMLAttribute) {
>       return;
>     }
> -    // Œ}„ü≠·≠é√Ê‚u≠›‚T≠·
> +    // ï¿∏}ï¿∏ï¿∏ï¿∏Ê‚uï¿∏ï¿∏Tï¿∏ï¿∏
>     FuzzyXMLNode target = null;
>     int index = -1;
>     FuzzyXMLNode[] children = getChildren();
> @@ -351,7 +353,7 @@
>       return;
>     }
>     int offset = target.getOffset();
> -    // ∞C∞x∞„∞g≠̉–≈Î
> +    // ï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏̉ï¿∏ï¿∏ï¿∏
>     fireModifyEvent(newChild.toXMLString(new RenderContext(getDocument().isHTML())), offset, 0);
> 
>     AbstractFuzzyXMLNode nodeImpl = (AbstractFuzzyXMLNode) newChild;
> @@ -360,19 +362,19 @@
>     nodeImpl.setOffset(offset);
>     nodeImpl.setLength(newChild.toXMLString(new RenderContext(getDocument().isHTML())).length());
> 
> -    // √Ê‚u∂îñ≠ÌŸX∆V
> +    // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ÌŸXï¿∏V
>     appendOffset(this, offset, nodeImpl.toXMLString(new RenderContext(getDocument().isHTML())).length());
> 
> -    // ŸÅ‘ã≠É‚Ç≈Á
> +    // ï¿∏Å‘ï¿∏É‚Ç≈ï¿∏
>     this._children.add(index, nodeImpl);
>   }
> 
>   public void replaceChild(FuzzyXMLNode newChild, FuzzyXMLNode refChild) {
> -    // ∞A∞g∞…∞r∞∑™[∞g≠Ì∂êŸΩ≠Í≠È≠É≠à≠µ≠È≠¢
> +    // ï¿∏Aï¿∏gï¿∏ï¿∏ï¿∏rï¿∏ï¿∏ï¿∏[ï¿∏gï¿∏Ì∂êŸΩï¿∏Í≠È≠É≠ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏
>     if (newChild instanceof FuzzyXMLAttribute || refChild instanceof FuzzyXMLAttribute) {
>       return;
>     }
> -    // ‚u…·≠·≠é∞m™[∞h≠Ì∞C∞„∞f∞b∞N∞X≠›⁄æ„≤
> +    // ï¿∏uï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏mï¿∏[ï¿∏hï¿∏Ì∞Cï¿∏ï¿∏ï¿∏fï¿∏bï¿∏Nï¿∏Xï¿∏ï¿∏ï¿∏æ„≤
>     int index = -1;
>     for (int i = 0; i < _children.size(); i++) {
>       if (refChild == _children.get(i)) {
> @@ -380,7 +382,7 @@
>         break;
>       }
>     }
> -    // ∞m™[∞h≠ª‘©≠Â≠©≠ç≠È≠©≠Á≠∏≠ç≠È≠É≠à≠µ≠È≠¢
> +    // ï¿∏mï¿∏[ï¿∏hï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Â≠ï¿∏ï¿∏ï¿∏È≠ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏È≠É≠ï¿∏ï¿∏ï¿∏ï¿∏È≠ï¿∏
>     if (index == -1) {
>       return;
>     }
> @@ -392,9 +394,9 @@
>     nodeImpl.setOffset(refChild.getOffset());
>     nodeImpl.setLength(newChild.toXMLString(new RenderContext(getDocument().isHTML())).length());
> 
> -    // ∞C∞x∞„∞g≠̉–≈Î
> +    // ï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏̉ï¿∏ï¿∏ï¿∏
>     fireModifyEvent(newChild.toXMLString(new RenderContext(getDocument().isHTML())), refChild.getOffset(), refChild.getLength());
> -    // √Ê‚u∂îñ≠ÌŸX∆V
> +    // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ÌŸXï¿∏V
>     appendOffset(this, refChild.getOffset(), newChild.getLength() - refChild.getLength());
> 
>     _children.add(index, newChild);
> @@ -406,14 +408,14 @@
>       return;
>     }
>     if (_children.contains(oldChild)) {
> -      // ∞f∞^∞b∞`
> +      // ï¿∏fï¿∏^ï¿∏bï¿∏`
>       ((AbstractFuzzyXMLNode) oldChild).setParentNode(null);
>       ((AbstractFuzzyXMLNode) oldChild).setDocument(null);
> -      // ∞…∞X∞g≠©≠çŸí∂˛
> +      // ï¿∏ï¿∏ï¿∏Xï¿∏gï¿∏ï¿∏ï¿∏ï¿∏í∂˛
>       _children.remove(oldChild);
> -      // ∞C∞x∞„∞g≠̉–≈Î
> +      // ï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏̉ï¿∏ï¿∏ï¿∏
>       fireModifyEvent("", oldChild.getOffset(), oldChild.getLength());
> -      // √Ê‚u∂îñ≠ÌŸX∆V
> +      // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ÌŸXï¿∏V
>       appendOffset(this, oldChild.getOffset(), oldChild.getLength() * -1);
>     }
>   }
> @@ -431,23 +433,23 @@
>       FuzzyXMLAttributeImpl attrImpl = (FuzzyXMLAttributeImpl) attr;
>       attrImpl.setDocument(getDocument());
>       attrImpl.setParentNode(this);
> -      // ‚Ç≈Á≠·≠é∞A∞g∞…∞r∞∑™[∞g≠Ì√Ê‚u≠›‘ƒŸõ
> +      // ï¿∏Ç≈ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Aï¿∏gï¿∏ï¿∏ï¿∏rï¿∏ï¿∏ï¿∏[ï¿∏gï¿∏Ì√Ê‚uï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏
>       FuzzyXMLAttribute[] attrs = getAttributes();
>       int offset = getOffset() + getName().length() + 1;
>       for (int i = 0; i < attrs.length; i++) {
>         offset = offset + attrs[i].toXMLString(new RenderContext(getDocument().isHTML())).length();
>       }
> -      // ŸX∆V∞C∞x∞„∞g≠›‰–≈Î
> +      // ï¿∏Xï¿∏Vï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏›‰–≈ï¿∏
>       fireModifyEvent(attr.toXMLString(new RenderContext(getDocument().isHTML())), offset, 0);
> -      // √Ê‚u∂îñ≠ÌŸX∆V
> +      // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ÌŸXï¿∏V
>       appendOffset(this, offset, attr.toXMLString(new RenderContext(getDocument().isHTML())).length());
> -      // ŸÅ‘ã≠É‚Ç≈Á
> +      // ï¿∏Å‘ï¿∏É‚Ç≈ï¿∏
>       attrImpl.setOffset(offset);
>       attrImpl.setLength(attrImpl.toXMLString(new RenderContext(getDocument().isHTML())).length());
>       _attributes.add(attrImpl);
>     }
>     else {
> -      // ≠±≠Ì∂êŸΩ≠Í∞A∞g∞…∞r∞∑™[∞g≠ÌsetValue∞™∞\∞b∞h„à≠Å∞C∞x∞„∞g‰–≈Î
> +      // ï¿∏ï¿∏ï¿∏Ì∂êŸΩï¿∏Í∞Aï¿∏gï¿∏ï¿∏ï¿∏rï¿∏ï¿∏ï¿∏[ï¿∏gï¿∏ï¿∏setValueï¿∏ï¿∏ï¿∏\ï¿∏bï¿∏hï¿∏ï¿∏ï¿∏Å∞Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏ï¿∏ï¿∏ï¿∏
>       FuzzyXMLAttributeImpl attrImpl = (FuzzyXMLAttributeImpl) attrNode;
>       attrImpl.setValue(attr.getValue());
>     }
> @@ -479,14 +481,14 @@
> 
>   public void removeAttributeNode(FuzzyXMLAttribute attr) {
>     if (_attributes.contains(attr)) {
> -      // ∞f∞^∞b∞`
> +      // ï¿∏fï¿∏^ï¿∏bï¿∏`
>       ((AbstractFuzzyXMLNode) attr).setParentNode(null);
>       ((AbstractFuzzyXMLNode) attr).setDocument(null);
> -      // ∞…∞X∞g≠©≠çŸí∂˛
> +      // ï¿∏ï¿∏ï¿∏Xï¿∏gï¿∏ï¿∏ï¿∏ï¿∏í∂˛
>       _attributes.remove(attr);
> -      // ∞C∞x∞„∞g≠̉–≈Î
> +      // ï¿∏Cï¿∏xï¿∏ï¿∏ï¿∏gï¿∏̉ï¿∏ï¿∏ï¿∏
>       fireModifyEvent("", attr.getOffset(), attr.getLength());
> -      // √Ê‚u∂îñ≠ÌŸX∆V
> +      // ï¿∏Ê‚uï¿∏ï¿∏ï¿∏ÌŸXï¿∏V
>       appendOffset(this, attr.getOffset(), attr.getLength() * -1);
>     }
>   }
> @@ -549,6 +551,10 @@
>   }
> 
>   public void toXMLString(RenderContext renderContext, StringBuffer xmlBuffer) {
> +  	if (isSynthetic()) {
> +  		return;
> +  	}
> +  	
>     boolean isHTML = renderContext.isHtml();
> 
>     boolean renderSurroundingTags = true;
> @@ -614,12 +620,12 @@
>     if (obj instanceof FuzzyXMLElement) {
>       FuzzyXMLElement element = (FuzzyXMLElement) obj;
> 
> -      // ∞^∞O≠̈πŒO≠ª√á≠Á≠∏≠çfalse
> +      // ï¿∏^ï¿∏Oï¿∏̈ï¿∏ï¿∏Oï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏false
>       if (!element.getName().equals(getName())) {
>         return false;
>       }
> 
> -      // ∆e≠ª˜πû≠Æ≠ànull≠≤≠Á≠∏≠çtrue
> +      // ï¿∏eï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏Æ≠ï¿∏nullï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏true
>       FuzzyXMLNode parent = element.getParentNode();
>       if (parent == null) {
>         if (getParentNode() == null) {
> @@ -628,7 +634,7 @@
>         return false;
>       }
> 
> -      // …J⁄n∞I∞t∞Z∞b∞g≠ª„¯≠¶≠≤≠Á≠∏≠çtrue
> +      // ï¿∏Jï¿∏nï¿∏Iï¿∏tï¿∏Zï¿∏bï¿∏gï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏ï¿∏true
>       if (element.getOffset() == getOffset()) {
>         return true;
>       }
> @@ -781,4 +787,12 @@
>   public boolean isHidden() {
>     return getName() == null || getName().equals("");
>   }
> +  
> +  public void setSynthetic(boolean synthetic) {
> +  	_synthetic = synthetic;
> +  }
> +  
> +  public boolean isSynthetic() {
> +  	return _synthetic;
> +  }
> }
> 
> Modified: branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLFormatComposite.java
> ===================================================================
> --- branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLFormatComposite.java	2010-10-03 21:15:19 UTC (rev 6167)
> +++ branches/eclipse_3_6/wolips/core/plugins/org.objectstyle.wolips.wodclipse.core/java/jp/aonir/fuzzyxml/internal/FuzzyXMLFormatComposite.java	2010-10-03 21:16:16 UTC (rev 6168)
> @@ -332,4 +332,9 @@
>     }
>     return false;
>   }
> +
> +	public boolean isSynthetic() {
> +    FuzzyXMLNode _node = unwrap(delegate); 
> +    return _node.isSynthetic();
> +	}
> }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.