Index: xword/ContentFiltering/Office/Word/AbstractConverter.cs =================================================================== --- xword/ContentFiltering/Office/Word/AbstractConverter.cs (revision 20624) +++ xword/ContentFiltering/Office/Word/AbstractConverter.cs (working copy) @@ -6,7 +6,7 @@ namespace XWiki.Office.Word { - class AbstractConverter + public class AbstractConverter { protected string DOCTYPE = "" + Environment.NewLine; Index: xword/ContentFiltering/Office/Word/LocalToWebHTML.cs =================================================================== --- xword/ContentFiltering/Office/Word/LocalToWebHTML.cs (revision 20624) +++ xword/ContentFiltering/Office/Word/LocalToWebHTML.cs (working copy) @@ -6,10 +6,11 @@ using System.Xml; using System.Xml.XPath; using XWiki.Xml; +using System.Collections; namespace XWiki.Office.Word { - class LocalToWebHTML : AbstractConverter + public class LocalToWebHTML : AbstractConverter { public LocalToWebHTML(ConversionManager manager) @@ -213,7 +214,7 @@ bool foundExtraLists = false; do { - //foundExtraLists = RemoveExtraLists(ref xmlDoc); + foundExtraLists = RemoveExtraLists(ref xmlDoc); } while (foundExtraLists); //Remove attributes from list declarations. XmlNodeList lists = xmlDoc.GetElementsByTagName("ul"); @@ -226,6 +227,9 @@ { node.Attributes.RemoveAll(); } + RemoveDivFromLists(ref xmlDoc, "ul"); + RemoveDivFromLists(ref xmlDoc, "ol"); + MoveChildListToTheirParent(ref xmlDoc); } /// @@ -239,13 +243,19 @@ XmlNodeList listItems = xmlDoc.GetElementsByTagName("li"); foreach (XmlNode node in listItems) { - if (node.NodeType == XmlNodeType.Element && node.ChildNodes.Count == 1) + //A 'li' with no innerText but with 'ul' or 'ol' children should be moved up + if (node.NodeType == XmlNodeType.Element && (""+node.Value).Length<1) { if (node.ChildNodes[0].Name == "ul" || node.ChildNodes[0].Name == "ol") { XmlNode prevListItem = node.PreviousSibling; - XmlNode subList = node.RemoveChild(node.FirstChild); - prevListItem.AppendChild(subList); + //XmlNode subList = node.RemoveChild(node.FirstChild); + XmlNodeList children = node.ChildNodes; + foreach (XmlNode child in children) + { + prevListItem.AppendChild(child); + } + //prevListItem.AppendChild(subList); foundExtraLists = true; } } @@ -254,6 +264,104 @@ } /// + /// Remove 'div' elements used for alignment and move their children in the correct position. + /// + /// A reference to the xml document. + /// List type/name (like "ol", "ul"). + private void RemoveDivFromLists(ref XmlDocument xmlDoc,string listName) + { + XmlNodeList lists = xmlDoc.GetElementsByTagName(listName); + Dictionary> childrenToMoveUp = new Dictionary>(); + foreach (XmlNode node in lists) + { + if (node.Name.ToLower().Trim() == "div") + { + XmlNode prevListItem = node.PreviousSibling; + XmlNode parent = node.ParentNode; + List value = new List(); + if (prevListItem != null) + { + if (childrenToMoveUp.ContainsKey(prevListItem)) + { + value = childrenToMoveUp[prevListItem]; + } + value.Add(node); + childrenToMoveUp.Add(prevListItem, value); + } + } + } + + foreach (XmlNode key in childrenToMoveUp.Keys) + { + XmlNode prevListItem = (XmlNode)key; + XmlNode parent = prevListItem.ParentNode; + List nodes = childrenToMoveUp[key]; + foreach (XmlNode node in nodes) + { + //take all the children from this div and put them in the right position + foreach (XmlNode child in node.ChildNodes) + { + parent.InsertAfter(child, prevListItem); + } + //remove the node + parent.RemoveChild(node); + } + } + + } + + /// + /// Move orphan 'ul' and 'ol' elements to their coresponding 'li' parent. + /// + /// A reference to the xml document. + private void MoveChildListToTheirParent(ref XmlDocument xmlDoc) + { + MoveElementsUp(ref xmlDoc, "ul"); + MoveElementsUp(ref xmlDoc, "ol"); + } + + /// + /// Move an element from an inner list to it's correct position. + /// + /// A reference to the xml document. + /// Element type/name (like "ol", "ul"). + private void MoveElementsUp(ref XmlDocument xmlDoc, string element) + { + Dictionary> childrenToMoveUp = new Dictionary>(); + + XmlNodeList items = xmlDoc.GetElementsByTagName(element.ToLower().Trim()); + foreach (XmlNode node in items) + { + XmlNode prevListItem = node.PreviousSibling; + XmlNode parent = node.ParentNode; + List value = new List(); + if (prevListItem != null) + { + if (prevListItem.Name.ToLower().Trim() == "li") + { + if (childrenToMoveUp.ContainsKey(prevListItem)) + { + value = childrenToMoveUp[prevListItem]; + } + value.Add(node); + childrenToMoveUp.Add(prevListItem, value); + } + } + } + foreach (XmlNode key in childrenToMoveUp.Keys) + { + XmlNode liParent = (XmlNode)key; + XmlNode parent = liParent.ParentNode; + List nodes = childrenToMoveUp[key]; + foreach (XmlNode node in nodes) + { + parent.RemoveChild(node); + liParent.AppendChild(node); + } + } + } + + /// /// Specifies if an image is new or has been modified. /// /// The XML node(element) that contains the image tag Index: xword/ContentFiltering/Office/Word/WebToLocalHTML.cs =================================================================== --- xword/ContentFiltering/Office/Word/WebToLocalHTML.cs (revision 20624) +++ xword/ContentFiltering/Office/Word/WebToLocalHTML.cs (working copy) @@ -10,6 +10,7 @@ using XWiki.Clients; using XWiki.Html; using XWiki.Xml; +using System.Collections; namespace XWiki.Office.Word { @@ -109,11 +110,59 @@ return "Sorry, a problem appeared when loading the page"; } AdaptMacros(ref xmlDoc); - AdaptImages(ref xmlDoc); + AdaptImages(ref xmlDoc); + AdaptLists(ref xmlDoc); return xmlDoc.GetIndentedXml(); } /// + /// Adapts the HTML lists to lists known by MS Word, because Word doesn't like + /// 'ul' inside 'li' elements with innerText. + /// + /// + private void AdaptLists(ref XmlDocument xmlDoc) + { + Dictionary> itemsToMoveUp = new Dictionary>(); + XmlNodeList listItems = xmlDoc.GetElementsByTagName("li"); + + //itentify
  • elements with
      children + foreach (XmlNode node in listItems) + { + XmlNodeList children=node.ChildNodes; + //only nodes with both text and other xml elements + if ((""+node.Value).Length < 1) + { + continue; + } + + foreach (XmlNode child in children) + { + if (child.Name.ToLower().Trim() == "ul" || child.Name.ToLower().Trim() == "ol") + { + List value=new List(); + + if (itemsToMoveUp.ContainsKey(node)) + { + value = itemsToMoveUp[node]; + } + value.Add(child); + itemsToMoveUp.Add(node,value); + } + } + } + + //move
        elements one level up if they are inside
      • elements with no innerText + foreach (XmlNode node in itemsToMoveUp.Keys) + { + foreach(XmlNode child in itemsToMoveUp[node]) + { + XmlNode n=node.RemoveChild(child); + node.ParentNode.InsertAfter(n,node); + } + } + } + + /// /// Adapts the html source to convert XWiki macros to Word Content Controls. /// /// A reference to the xml dom containing the source. @@ -229,7 +278,6 @@ element.Attributes.Append(id); return element; } - /// /// Adapts the html source returned by the XWiki server and makes it usable by Word using a local html file. /// @@ -279,14 +327,7 @@ } } - /// - /// Adapts lthe lists from the XWiki server to a format used by Word. - /// - /// - private void AdaptLists(ref XmlDocument xmlDoc) - { - throw new NotImplementedException(); - } + /// /// Downloads the image from the server and saves it to a local file.