<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://freemind.sourceforge.io/wiki/index.php?action=history&amp;feed=atom&amp;title=User%3AJiangxin%2FPatch_save_extra_attributes_outof_mmfile</id>
	<title>User:Jiangxin/Patch save extra attributes outof mmfile - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://freemind.sourceforge.io/wiki/index.php?action=history&amp;feed=atom&amp;title=User%3AJiangxin%2FPatch_save_extra_attributes_outof_mmfile"/>
	<link rel="alternate" type="text/html" href="https://freemind.sourceforge.io/wiki/index.php?title=User:Jiangxin/Patch_save_extra_attributes_outof_mmfile&amp;action=history"/>
	<updated>2026-04-23T08:52:20Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.38.7</generator>
	<entry>
		<id>https://freemind.sourceforge.io/wiki/index.php?title=User:Jiangxin/Patch_save_extra_attributes_outof_mmfile&amp;diff=10754&amp;oldid=prev</id>
		<title>Jiangxin: patch for freemind 0.9</title>
		<link rel="alternate" type="text/html" href="https://freemind.sourceforge.io/wiki/index.php?title=User:Jiangxin/Patch_save_extra_attributes_outof_mmfile&amp;diff=10754&amp;oldid=prev"/>
		<updated>2007-03-15T08:42:39Z</updated>

		<summary type="html">&lt;p&gt;patch for freemind 0.9&lt;/p&gt;
&lt;a href=&quot;https://freemind.sourceforge.io/wiki/index.php?title=User:Jiangxin/Patch_save_extra_attributes_outof_mmfile&amp;amp;diff=10754&amp;amp;oldid=4320&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Jiangxin</name></author>
	</entry>
	<entry>
		<id>https://freemind.sourceforge.io/wiki/index.php?title=User:Jiangxin/Patch_save_extra_attributes_outof_mmfile&amp;diff=4320&amp;oldid=prev</id>
		<title>Jiangxin: initial</title>
		<link rel="alternate" type="text/html" href="https://freemind.sourceforge.io/wiki/index.php?title=User:Jiangxin/Patch_save_extra_attributes_outof_mmfile&amp;diff=4320&amp;oldid=prev"/>
		<updated>2006-04-06T17:23:16Z</updated>

		<summary type="html">&lt;p&gt;initial&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Why this patch?==&lt;br /&gt;
All my .mm files are version controled using CVS/SVN. What FreeMind has scratched my personal itch:&lt;br /&gt;
*Some attributes of FreeMind&amp;#039;s .mm file are not suitable for version control. &lt;br /&gt;
*e.g., &amp;#039;FOLDED&amp;#039; attribute saved in .mm file, makes documents changed frequently and unnecessarily. &lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
*Save extra attributes into another file, named *.mmx&lt;br /&gt;
*defined three attlist.&lt;br /&gt;
**attributes listed in WhiteAttlist are the only attributes should be saved to files.&lt;br /&gt;
**attributes listed in BlackAttlist are the attributes shouldn&amp;#039;t be saved to files.&lt;br /&gt;
**attributes listed in EmAttlist will be list in a single line. (a kind of EMphasis)&lt;br /&gt;
&lt;br /&gt;
Attributes saved in .mmx file will be loaded when .mm file is open. Please see another patch:&lt;br /&gt;
*[[User:Jiangxin/Patch_load_mm_file_with_mmx_file]]&lt;br /&gt;
&lt;br /&gt;
==Patch file==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;Index: freemind/freemind/main/FreeMind.java&lt;br /&gt;
===================================================================&lt;br /&gt;
--- freemind/freemind/main/FreeMind.java	(.../tags/RELEASE-0-8-0)	(revision 2)&lt;br /&gt;
+++ freemind/freemind/main/FreeMind.java	(.../branches/WHFM-0-8-0)	(working copy)&lt;br /&gt;
@@ -86,6 +86,7 @@&lt;br /&gt;
     private static final String DEFAULT_LANGUAGE = &amp;quot;en&amp;quot;;&lt;br /&gt;
     private HookFactory nodeHookFactory;&lt;br /&gt;
 	public static final String version = &amp;quot;0.8.0&amp;quot;;&lt;br /&gt;
+    public static final String DEFAULT_CHARSET = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;
     //    public static final String defaultPropsURL = &amp;quot;freemind.properties&amp;quot;;&lt;br /&gt;
     public URL defaultPropsURL;&lt;br /&gt;
     //    public static Properties defaultProps;&lt;br /&gt;
Index: freemind/freemind/main/XMLElement.java&lt;br /&gt;
===================================================================&lt;br /&gt;
--- freemind/freemind/main/XMLElement.java	(.../tags/RELEASE-0-8-0)	(revision 2)&lt;br /&gt;
+++ freemind/freemind/main/XMLElement.java	(.../branches/WHFM-0-8-0)	(working copy)&lt;br /&gt;
@@ -258,7 +258,58 @@&lt;br /&gt;
      */&lt;br /&gt;
     private int parserLineNr;&lt;br /&gt;
 &lt;br /&gt;
+    private String special_attlist[];&lt;br /&gt;
 &lt;br /&gt;
+    private void _addtoAttlist(int list, String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	if (list &amp;gt;= special_attlist.length || list &amp;lt;0)&lt;br /&gt;
+    		return;&lt;br /&gt;
+    	this.special_attlist[list] += att;&lt;br /&gt;
+    	this.special_attlist[list] += &amp;quot;:&amp;quot;;&lt;br /&gt;
+    	return;&lt;br /&gt;
+    }&lt;br /&gt;
+    &lt;br /&gt;
+    private boolean _isInAttlist(int list, String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	if ( list &amp;gt;= special_attlist.length || list &amp;lt;0 || special_attlist[list].length()==0 ) {&lt;br /&gt;
+    		return false;&lt;br /&gt;
+    	}&lt;br /&gt;
+    	return this.special_attlist[list].contains(att+&amp;#039;:&amp;#039;);&lt;br /&gt;
+    }&lt;br /&gt;
+&lt;br /&gt;
+    public boolean isInWhiteAttlist(String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	if ( this.special_attlist[0].length()==0 ) {&lt;br /&gt;
+    		return true;&lt;br /&gt;
+    	}&lt;br /&gt;
+    	return _isInAttlist(0, att);&lt;br /&gt;
+    }&lt;br /&gt;
+&lt;br /&gt;
+    public boolean isInBlackAttlist(String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	return _isInAttlist(1, att);&lt;br /&gt;
+    }&lt;br /&gt;
+&lt;br /&gt;
+    public boolean isInEmAttlist(String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	return _isInAttlist(2, att);&lt;br /&gt;
+    }&lt;br /&gt;
+&lt;br /&gt;
+    public void addtoWhiteAttlist(String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	_addtoAttlist(0, att);&lt;br /&gt;
+    }&lt;br /&gt;
+&lt;br /&gt;
+    public void addtoBlackAttlist(String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	_addtoAttlist(1, att);&lt;br /&gt;
+    }&lt;br /&gt;
+&lt;br /&gt;
+    public void addtoEmAttlist(String att)&lt;br /&gt;
+    {&lt;br /&gt;
+    	_addtoAttlist(2, att);&lt;br /&gt;
+    }&lt;br /&gt;
+    &lt;br /&gt;
     /**&lt;br /&gt;
      * Creates and initializes a new XML element.&lt;br /&gt;
      * Calling the construction is equivalent to:&lt;br /&gt;
@@ -484,6 +535,10 @@&lt;br /&gt;
         this.children = new Vector();&lt;br /&gt;
         this.entities = entities;&lt;br /&gt;
         this.lineNr = 0;&lt;br /&gt;
+        this.special_attlist = new String[3];&lt;br /&gt;
+        for (int i = 0; i &amp;lt; 3; i++) {&lt;br /&gt;
+            special_attlist[i] = &amp;quot;&amp;quot;;&lt;br /&gt;
+        }&lt;br /&gt;
         Enumeration enumerator = this.entities.keys();&lt;br /&gt;
         while (enumerator.hasMoreElements()) {&lt;br /&gt;
             Object key = enumerator.nextElement();&lt;br /&gt;
@@ -2200,9 +2256,25 @@&lt;br /&gt;
         if (! this.attributes.isEmpty()) {&lt;br /&gt;
             Iterator enumerator = this.attributes.keySet().iterator();&lt;br /&gt;
             while (enumerator.hasNext()) {&lt;br /&gt;
-                writer.write(&amp;#039; &amp;#039;);&lt;br /&gt;
                 String key = (String) enumerator.next();&lt;br /&gt;
                 String value = (String) this.attributes.get(key);&lt;br /&gt;
+&lt;br /&gt;
+                if ( this.isInBlackAttlist(key) )&lt;br /&gt;
+                {&lt;br /&gt;
+                	continue;&lt;br /&gt;
+                }&lt;br /&gt;
+                else if ( ! this.isInWhiteAttlist(key) )&lt;br /&gt;
+                {&lt;br /&gt;
+                	continue;&lt;br /&gt;
+                }&lt;br /&gt;
+&lt;br /&gt;
+                writer.write(&amp;#039; &amp;#039;);&lt;br /&gt;
+&lt;br /&gt;
+                if ( this.isInEmAttlist(key) )&lt;br /&gt;
+                {&lt;br /&gt;
+                	writer.write(&amp;quot;\n\t&amp;quot;);&lt;br /&gt;
+                }&lt;br /&gt;
+&lt;br /&gt;
                 writer.write(key);&lt;br /&gt;
                 writer.write(&amp;#039;=&amp;#039;); writer.write(&amp;#039;&amp;quot;&amp;#039;);&lt;br /&gt;
                 this.writeEncoded(writer, value);&lt;br /&gt;
Index: freemind/freemind/modes/mindmapmode/MindMapMapModel.java&lt;br /&gt;
===================================================================&lt;br /&gt;
--- freemind/freemind/modes/mindmapmode/MindMapMapModel.java	(.../tags/RELEASE-0-8-0)	(revision 2)&lt;br /&gt;
+++ freemind/freemind/modes/mindmapmode/MindMapMapModel.java	(.../branches/WHFM-0-8-0)	(working copy)&lt;br /&gt;
@@ -49,13 +49,18 @@&lt;br /&gt;
 import java.util.TimerTask;&lt;br /&gt;
 import java.util.Vector;&lt;br /&gt;
 &lt;br /&gt;
+import javax.xml.parsers.DocumentBuilder;&lt;br /&gt;
+import javax.xml.parsers.DocumentBuilderFactory;&lt;br /&gt;
 import javax.xml.transform.Result;&lt;br /&gt;
 import javax.xml.transform.Source;&lt;br /&gt;
 import javax.xml.transform.Transformer;&lt;br /&gt;
 import javax.xml.transform.TransformerFactory;&lt;br /&gt;
+import javax.xml.transform.dom.DOMSource;&lt;br /&gt;
 import javax.xml.transform.stream.StreamResult;&lt;br /&gt;
 import javax.xml.transform.stream.StreamSource;&lt;br /&gt;
 &lt;br /&gt;
+import org.w3c.dom.Document;&lt;br /&gt;
+&lt;br /&gt;
 import freemind.controller.MindMapNodesSelection;&lt;br /&gt;
 import freemind.main.FreeMind;&lt;br /&gt;
 import freemind.main.FreeMindMain;&lt;br /&gt;
@@ -414,9 +419,25 @@&lt;br /&gt;
             return false; }&lt;br /&gt;
         try {            &lt;br /&gt;
             //Generating output Stream            &lt;br /&gt;
-            BufferedWriter fileout = new BufferedWriter( new OutputStreamWriter( new FileOutputStream(file) ) );&lt;br /&gt;
-            getXml(fileout);&lt;br /&gt;
+            // TODO user can define his/her own charset.&lt;br /&gt;
+            BufferedWriter fileout = new BufferedWriter( new OutputStreamWriter( new FileOutputStream(file), FreeMind.DEFAULT_CHARSET ) );&lt;br /&gt;
+            getXml(fileout, 0);&lt;br /&gt;
 &lt;br /&gt;
+            // Save FOLDED attrib into .mmx file...&lt;br /&gt;
+            String ext = Tools.getExtension(file.getName());&lt;br /&gt;
+            String mmxFileName = &amp;quot;&amp;quot;;&lt;br /&gt;
+            if(!ext.equals(&amp;quot;mm&amp;quot;)) &lt;br /&gt;
+            {&lt;br /&gt;
+            	mmxFileName = file.getName()+&amp;quot;.mmx&amp;quot;;&lt;br /&gt;
+            }&lt;br /&gt;
+            else &lt;br /&gt;
+            {&lt;br /&gt;
+            	mmxFileName = Tools.removeExtension(file.getName()) + &amp;quot;.mmx&amp;quot;;&lt;br /&gt;
+            }&lt;br /&gt;
+            File mmxfile = new File(file.getParent(), mmxFileName); &lt;br /&gt;
+            BufferedWriter mmxfileout = new BufferedWriter( new OutputStreamWriter( new FileOutputStream(mmxfile), FreeMind.DEFAULT_CHARSET ) );&lt;br /&gt;
+            getXml(mmxfileout, 1);&lt;br /&gt;
+&lt;br /&gt;
             if(!isInternal) {&lt;br /&gt;
                 setFile(file);            &lt;br /&gt;
                 setSaved(true);&lt;br /&gt;
@@ -440,11 +461,33 @@&lt;br /&gt;
     /** writes the content of the map to a writer.&lt;br /&gt;
 	 * @param fileout&lt;br /&gt;
 	 * @throws IOException&lt;br /&gt;
+	 * @param managed_attr =0|1|2&lt;br /&gt;
+	 *         0 (default): do not check FOLDED attribute(make all nodes folded), saved in .mm file.&lt;br /&gt;
+	 *         1          : only check and save FOLDED attributes in .mmx file.&lt;br /&gt;
+	 *         2          : save all attributes in one single .mm file.&lt;br /&gt;
 	 */&lt;br /&gt;
 	public void getXml(Writer fileout) throws IOException {&lt;br /&gt;
+		getXml(fileout, 0);&lt;br /&gt;
+	}&lt;br /&gt;
+&lt;br /&gt;
+	public void getXml(Writer fileout, int managed_attr) throws IOException {&lt;br /&gt;
+		// TODO user can define his/her own charset.&lt;br /&gt;
+		fileout.write(&amp;quot;&amp;lt;?xml version=\&amp;quot;1.0\&amp;quot; encoding=\&amp;quot;&amp;quot; + FreeMind.DEFAULT_CHARSET + &amp;quot;\&amp;quot;?&amp;gt;\n&amp;quot;);&lt;br /&gt;
 		fileout.write(&amp;quot;&amp;lt;map version=\&amp;quot;&amp;quot;+getFrame().getFreemindVersion()+&amp;quot;\&amp;quot;&amp;gt;\n&amp;quot;);&lt;br /&gt;
-		fileout.write(&amp;quot;&amp;lt;!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net --&amp;gt;\n&amp;quot;);&lt;br /&gt;
-		((MindMapNodeModel)getRoot()).save(fileout, this.getLinkRegistry());&lt;br /&gt;
+		switch (managed_attr)&lt;br /&gt;
+		{&lt;br /&gt;
+		case 0:&lt;br /&gt;
+			fileout.write(&amp;quot;&amp;lt;!-- This .mm file is CVS/SVN friendly, also has better Chinese character support. Contribute by http://www.WorldHello.net, orignal FreeMind can be found at http://freemind.sourceforge.net --&amp;gt;\n&amp;quot;);&lt;br /&gt;
+			break;&lt;br /&gt;
+		case 1:&lt;br /&gt;
+			fileout.write(&amp;quot;&amp;lt;!-- .mmx files store some extra mm file attributes, which should not check in to CVS/SVN --&amp;gt;\n&amp;quot;);&lt;br /&gt;
+			break;&lt;br /&gt;
+		case 2:&lt;br /&gt;
+		default:&lt;br /&gt;
+			fileout.write(&amp;quot;&amp;lt;!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net --&amp;gt;\n&amp;quot;);&lt;br /&gt;
+			break;&lt;br /&gt;
+		}&lt;br /&gt;
+		((MindMapNodeModel)getRoot()).save(fileout, this.getLinkRegistry(), managed_attr);&lt;br /&gt;
 		fileout.write(&amp;quot;&amp;lt;/map&amp;gt;\n&amp;quot;);&lt;br /&gt;
 		fileout.close();&lt;br /&gt;
 	}&lt;br /&gt;
Index: freemind/freemind/modes/NodeAdapter.java&lt;br /&gt;
===================================================================&lt;br /&gt;
--- freemind/freemind/modes/NodeAdapter.java	(.../tags/RELEASE-0-8-0)	(revision 2)&lt;br /&gt;
+++ freemind/freemind/modes/NodeAdapter.java	(.../branches/WHFM-0-8-0)	(working copy)&lt;br /&gt;
@@ -826,7 +826,20 @@&lt;br /&gt;
 	    return controller.getNodeID(this);&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
+    /**&lt;br /&gt;
+     * @param writer&lt;br /&gt;
+     * @param registry&lt;br /&gt;
+     * @param managed_attr =0|1|2&lt;br /&gt;
+     *         0 (default): do not check FOLDED attribute(make all nodes folded), saved in .mm file.&lt;br /&gt;
+     *         1          : only check and save FOLDED attributes in .mmx file.&lt;br /&gt;
+     *         2          : save all attributes in one single .mm file.&lt;br /&gt;
+     * @return&lt;br /&gt;
+     */&lt;br /&gt;
     public XMLElement save(Writer writer, MindMapLinkRegistry registry) throws IOException {&lt;br /&gt;
+    	return save(writer, registry, 0);&lt;br /&gt;
+    }&lt;br /&gt;
+    &lt;br /&gt;
+    public XMLElement save(Writer writer, MindMapLinkRegistry registry, int managed_attr) throws IOException {&lt;br /&gt;
     	XMLElement node = new XMLElement();&lt;br /&gt;
     	&lt;br /&gt;
 //    	if (!isNodeClassToBeSaved()) {&lt;br /&gt;
@@ -863,8 +876,28 @@&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
             &lt;br /&gt;
-    	if (isFolded()) {&lt;br /&gt;
-               node.setAttribute(&amp;quot;FOLDED&amp;quot;,&amp;quot;true&amp;quot;); }&lt;br /&gt;
+    	// do not check FOLDED attribute, save all nodes as Folded, except root and leaf.&lt;br /&gt;
+        node.addtoEmAttlist(&amp;quot;TEXT&amp;quot;);&lt;br /&gt;
+        switch (managed_attr)&lt;br /&gt;
+    	{&lt;br /&gt;
+        case 0:&lt;br /&gt;
+        	if (!isRoot() &amp;amp;&amp;amp; !isLeaf()) {&lt;br /&gt;
+    			node.setAttribute(&amp;quot;FOLDED&amp;quot;,&amp;quot;true&amp;quot;);&lt;br /&gt;
+    		}&lt;br /&gt;
+           	node.addtoBlackAttlist(&amp;quot;CREATED&amp;quot;);&lt;br /&gt;
+           	node.addtoBlackAttlist(&amp;quot;MODIFIED&amp;quot;);&lt;br /&gt;
+        	break;&lt;br /&gt;
+        case 1:&lt;br /&gt;
+        	node.addtoWhiteAttlist(&amp;quot;ID&amp;quot;);&lt;br /&gt;
+        	node.addtoWhiteAttlist(&amp;quot;FOLDED&amp;quot;);&lt;br /&gt;
+           	node.addtoWhiteAttlist(&amp;quot;CREATED&amp;quot;);&lt;br /&gt;
+           	node.addtoWhiteAttlist(&amp;quot;MODIFIED&amp;quot;);&lt;br /&gt;
+        case 2:&lt;br /&gt;
+        default:&lt;br /&gt;
+                if (isFolded()) {&lt;br /&gt;
+                        node.setAttribute(&amp;quot;FOLDED&amp;quot;,&amp;quot;true&amp;quot;); &lt;br /&gt;
+                }&lt;br /&gt;
+    	}&lt;br /&gt;
     	&lt;br /&gt;
         // fc, 17.12.2003: Remove the left/right bug.&lt;br /&gt;
         //                       VVV  save if and only if parent is root.&lt;br /&gt;
@@ -950,7 +983,7 @@&lt;br /&gt;
             //recursive&lt;br /&gt;
             for (ListIterator e = childrenUnfolded(); e.hasNext();) {&lt;br /&gt;
                 NodeAdapter child = (NodeAdapter) e.next();&lt;br /&gt;
-                child.save(writer, registry);&lt;br /&gt;
+                child.save(writer, registry, managed_attr);&lt;br /&gt;
             }&lt;br /&gt;
             node.writeClosingTag(writer);&lt;br /&gt;
         } else {&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jiangxin</name></author>
	</entry>
</feed>