/// <summary> /// count occurrences of numbered lists, save that as a hint on the numbered list node /// </summary> /// <param name="mainDoc"></param> /// <param name="nsm"></param> private static void HandleNumberedLists(XmlDocument mainDoc, XmlNamespaceManager nsm) { // count the number of different list numbering schemes XmlNodeList numberNodes = mainDoc.SelectNodes("/w:document/w:numbering/w:num", nsm); if (numberNodes.Count == 0) { return; } // initialize the abstract number list XmlNodeList abstractNumNodes = mainDoc.SelectNodes("/w:document/w:numbering/w:abstractNum", nsm); Dictionary<string, AbstractListNumberingDefinition> abstractListDefinitions = new Dictionary<string, AbstractListNumberingDefinition>(abstractNumNodes.Count); Dictionary<string, ListNumberingDefinition> instanceListDefinitions = new Dictionary<string, ListNumberingDefinition>(numberNodes.Count); // store the abstract list type definitions foreach (XmlNode abstractNumNode in abstractNumNodes) { AbstractListNumberingDefinition absNumDef = new AbstractListNumberingDefinition(abstractNumNode, nsm); abstractListDefinitions[absNumDef.ID] = absNumDef; } // now go through the abstract list definitions and update those that are linked to other styles foreach (KeyValuePair<string, AbstractListNumberingDefinition> absNumDef in abstractListDefinitions) { if (absNumDef.Value.HasLinkedStyle) { // find the linked style string linkStyleXPath = "/w:document/w:numbering/w:abstractNum/w:styleLink[@w:val=\"" + absNumDef.Value.LinkedStyleId + "\"]"; XmlNode linkedStyleNode = mainDoc.SelectSingleNode(linkStyleXPath, nsm); if (linkedStyleNode != null) { absNumDef.Value.UpdateDefinitionFromLinkedStyle(linkedStyleNode.ParentNode, nsm); } } } // instantiate the list number definitions foreach (XmlNode numNode in numberNodes) { ListNumberingDefinition listDef = new ListNumberingDefinition(numNode, nsm, abstractListDefinitions); instanceListDefinitions[listDef.ListNumberId] = listDef; } // Get styles with numbering definitions XmlNodeList stylesWithNumbers = mainDoc.SelectNodes("/w:document/w:styles/w:style/w:pPr/w:numPr", nsm); Dictionary<string, StyleDefinition> styleDefinitions = new Dictionary<string, StyleDefinition>(stylesWithNumbers.Count); foreach (XmlNode styleNode in stylesWithNumbers) { // Check to see if it is based on a style that is not in the definitions list yet? StyleDefinition styleDef = new StyleDefinition(styleNode, nsm, styleDefinitions); styleDefinitions[styleDef.Name] = styleDef; } XmlNodeList styleParagraphs = mainDoc.SelectNodes("//w:pPr/w:pStyle", nsm); foreach (XmlNode paragraph in styleParagraphs) { string styleName = getAttributeValue(paragraph, ValAttrName); if (!String.IsNullOrEmpty(styleName) && styleDefinitions.ContainsKey(styleName)) { XmlNode oldNode = paragraph.ParentNode.SelectSingleNode("./w:numPr", nsm); if (oldNode == null) styleDefinitions[styleName].AddNumbering(mainDoc, paragraph.ParentNode); } } XmlNodeList listNodes = mainDoc.SelectNodes("//w:numPr/w:ilvl", nsm); foreach (XmlNode node in listNodes) { string levelId = getAttributeValue(node, ValAttrName); XmlNode numIdNode = node.ParentNode.SelectSingleNode("./w:numId", nsm); if (!String.IsNullOrEmpty(levelId) && numIdNode != null) { string numId = getAttributeValue(numIdNode, ValAttrName); if (!String.IsNullOrEmpty(numId) && instanceListDefinitions.ContainsKey(numId) && instanceListDefinitions[numId].LevelExists(levelId)) { XmlAttribute counterAttr = mainDoc.CreateAttribute("numString"); instanceListDefinitions[numId].IncrementCounter(levelId); counterAttr.Value = instanceListDefinitions[numId].GetCurrentNumberString(levelId) + " "; node.Attributes.Append(counterAttr); string font = instanceListDefinitions[numId].GetFont(levelId); if (!String.IsNullOrEmpty(font)) { XmlAttribute fontAttr = mainDoc.CreateAttribute("numFont"); fontAttr.Value = font; node.Attributes.Append(fontAttr); } if (instanceListDefinitions[numId].IsBullet(levelId)) { XmlAttribute bulletAttr = mainDoc.CreateAttribute("isBullet"); bulletAttr.Value = "true"; node.Attributes.Append(bulletAttr); } } } } }
/// <summary> /// constructor /// </summary> /// <param name="numNode"></param> /// <param name="nsm"></param> /// <param name="abstractListDefinitions"></param> public ListNumberingDefinition(XmlNode numNode, XmlNamespaceManager nsm, Dictionary<string, AbstractListNumberingDefinition> abstractListDefinitions) { this.listNumberId = getAttributeValue(numNode, "w:numId"); XmlNode abstractNumNode = numNode.SelectSingleNode("./w:abstractNumId", nsm); if (abstractNumNode != null) { this.abstractListDefinition = abstractListDefinitions[getAttributeValue(abstractNumNode, ValAttrName)]; // Create local overrides for the list number levels overrideLevels = new Dictionary<string, ListLevel>(); // propagate the level overrides into the current list number level definition XmlNodeList levelOverrideNodes = numNode.SelectNodes("./w:lvlOverride", nsm); if (levelOverrideNodes != null) { foreach (XmlNode overrideNode in levelOverrideNodes) { string overrideLevelId = getAttributeValue(overrideNode, "w:ilvl"); XmlNode node = overrideNode.SelectSingleNode("./w:lvl", nsm); if (node == null) node = overrideNode; if (!String.IsNullOrEmpty(overrideLevelId)) { ListLevel newLevel = new ListLevel(this.abstractListDefinition.ListLevels[overrideLevelId]); newLevel.SetOverrides(node, nsm); overrideLevels.Add(overrideLevelId, newLevel); } } } } }
/// <summary> /// count occurrences of numbered lists, save that as a hint on the numbered list node /// </summary> /// <param name="mainDoc"></param> /// <param name="nsm"></param> private static void HandleNumberedLists(XmlDocument mainDoc, XmlNamespaceManager nsm) { // count the number of different list numbering schemes XmlNodeList numberNodes = mainDoc.SelectNodes("/w:document/w:numbering/w:num", nsm); if (numberNodes.Count == 0) { return; } // initialize the abstract number list XmlNodeList abstractNumNodes = mainDoc.SelectNodes("/w:document/w:numbering/w:abstractNum", nsm); Dictionary <string, AbstractListNumberingDefinition> abstractListDefinitions = new Dictionary <string, AbstractListNumberingDefinition>(abstractNumNodes.Count); Dictionary <string, ListNumberingDefinition> instanceListDefinitions = new Dictionary <string, ListNumberingDefinition>(numberNodes.Count); // store the abstract list type definitions foreach (XmlNode abstractNumNode in abstractNumNodes) { AbstractListNumberingDefinition absNumDef = new AbstractListNumberingDefinition(abstractNumNode, nsm); abstractListDefinitions[absNumDef.ID] = absNumDef; } // now go through the abstract list definitions and update those that are linked to other styles foreach (KeyValuePair <string, AbstractListNumberingDefinition> absNumDef in abstractListDefinitions) { if (absNumDef.Value.HasLinkedStyle) { // find the linked style string linkStyleXPath = "/w:document/w:numbering/w:abstractNum/w:styleLink[@w:val=\"" + absNumDef.Value.LinkedStyleId + "\"]"; XmlNode linkedStyleNode = mainDoc.SelectSingleNode(linkStyleXPath, nsm); if (linkedStyleNode != null) { absNumDef.Value.UpdateDefinitionFromLinkedStyle(linkedStyleNode.ParentNode, nsm); } } } // instantiate the list number definitions foreach (XmlNode numNode in numberNodes) { ListNumberingDefinition listDef = new ListNumberingDefinition(numNode, nsm, abstractListDefinitions); instanceListDefinitions[listDef.ListNumberId] = listDef; } // Get styles with numbering definitions XmlNodeList stylesWithNumbers = mainDoc.SelectNodes("/w:document/w:styles/w:style/w:pPr/w:numPr", nsm); Dictionary <string, StyleDefinition> styleDefinitions = new Dictionary <string, StyleDefinition>(stylesWithNumbers.Count); foreach (XmlNode styleNode in stylesWithNumbers) { // Check to see if it is based on a style that is not in the definitions list yet? StyleDefinition styleDef = new StyleDefinition(styleNode, nsm, styleDefinitions); styleDefinitions[styleDef.Name] = styleDef; } XmlNodeList styleParagraphs = mainDoc.SelectNodes("//w:pPr/w:pStyle", nsm); foreach (XmlNode paragraph in styleParagraphs) { string styleName = getAttributeValue(paragraph, ValAttrName); if (!String.IsNullOrEmpty(styleName) && styleDefinitions.ContainsKey(styleName)) { XmlNode oldNode = paragraph.ParentNode.SelectSingleNode("./w:numPr", nsm); if (oldNode == null) { styleDefinitions[styleName].AddNumbering(mainDoc, paragraph.ParentNode); } } } XmlNodeList listNodes = mainDoc.SelectNodes("//w:numPr/w:ilvl", nsm); foreach (XmlNode node in listNodes) { string levelId = getAttributeValue(node, ValAttrName); XmlNode numIdNode = node.ParentNode.SelectSingleNode("./w:numId", nsm); if (!String.IsNullOrEmpty(levelId) && numIdNode != null) { string numId = getAttributeValue(numIdNode, ValAttrName); if (!String.IsNullOrEmpty(numId) && instanceListDefinitions.ContainsKey(numId) && instanceListDefinitions[numId].LevelExists(levelId)) { XmlAttribute counterAttr = mainDoc.CreateAttribute("numString"); instanceListDefinitions[numId].IncrementCounter(levelId); counterAttr.Value = instanceListDefinitions[numId].GetCurrentNumberString(levelId) + " "; node.Attributes.Append(counterAttr); string font = instanceListDefinitions[numId].GetFont(levelId); if (!String.IsNullOrEmpty(font)) { XmlAttribute fontAttr = mainDoc.CreateAttribute("numFont"); fontAttr.Value = font; node.Attributes.Append(fontAttr); } if (instanceListDefinitions[numId].IsBullet(levelId)) { XmlAttribute bulletAttr = mainDoc.CreateAttribute("isBullet"); bulletAttr.Value = "true"; node.Attributes.Append(bulletAttr); } } } } }