Upload to server
uploading
This commit is contained in:
633
omegapro/PowerTools/Classes/ListItemRetriever.cs
Normal file
633
omegapro/PowerTools/Classes/ListItemRetriever.cs
Normal file
@@ -0,0 +1,633 @@
|
||||
/***************************************************************************
|
||||
|
||||
Copyright (c) Microsoft Corporation 2010.
|
||||
|
||||
This code is licensed using the Microsoft Public License (Ms-PL). The text of the license
|
||||
can be found here:
|
||||
|
||||
http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using DocumentFormat.OpenXml.Packaging;
|
||||
|
||||
namespace OpenXmlPowerTools
|
||||
{
|
||||
public partial class WmlDocument : OpenXmlPowerToolsDocument
|
||||
{
|
||||
public string RetrieveListItem(XElement paragraph, string bulletReplacementString)
|
||||
{
|
||||
return ListItemRetriever.RetrieveListItem(this, paragraph, bulletReplacementString);
|
||||
}
|
||||
}
|
||||
|
||||
public class ListItemRetriever
|
||||
{
|
||||
private class ListItemInfo
|
||||
{
|
||||
public bool IsListItem;
|
||||
public XElement Lvl;
|
||||
public int? Start;
|
||||
public int? AbstractNumId;
|
||||
public ListItemInfo(bool isListItem)
|
||||
{
|
||||
IsListItem = isListItem;
|
||||
}
|
||||
}
|
||||
|
||||
private class LevelNumbers
|
||||
{
|
||||
public int[] LevelNumbersArray;
|
||||
}
|
||||
|
||||
private static ListItemInfo GetListItemInfoByNumIdAndIlvl(XDocument numbering,
|
||||
XDocument styles, int numId, int ilvl)
|
||||
{
|
||||
if (numId == 0)
|
||||
return new ListItemInfo(false);
|
||||
ListItemInfo listItemInfo = new ListItemInfo(true);
|
||||
XElement num = numbering.Root.Elements(W.num)
|
||||
.Where(e => (int)e.Attribute(W.numId) == numId).FirstOrDefault();
|
||||
if (num == null)
|
||||
return new ListItemInfo(false);
|
||||
listItemInfo.AbstractNumId = (int?)num.Elements(W.abstractNumId)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
XElement lvlOverride = num.Elements(W.lvlOverride)
|
||||
.Where(e => (int)e.Attribute(W.ilvl) == ilvl).FirstOrDefault();
|
||||
// If there is a w:lvlOverride element, and if the w:lvlOverride contains a
|
||||
// w:lvl element, then return it. Otherwise, go look in the abstract numbering
|
||||
// definition.
|
||||
if (lvlOverride != null)
|
||||
{
|
||||
// Get the startOverride, if there is one.
|
||||
listItemInfo.Start = (int?)num.Elements(W.lvlOverride)
|
||||
.Where(o => (int)o.Attribute(W.ilvl) == ilvl).Elements(W.startOverride)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
listItemInfo.Lvl = lvlOverride.Element(W.lvl);
|
||||
if (listItemInfo.Lvl != null)
|
||||
{
|
||||
if (listItemInfo.Start == null)
|
||||
listItemInfo.Start = (int?)listItemInfo.Lvl.Elements(W.start)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
return listItemInfo;
|
||||
}
|
||||
}
|
||||
int? a = listItemInfo.AbstractNumId;
|
||||
XElement abstractNum = numbering.Root.Elements(W.abstractNum)
|
||||
.Where(e => (int)e.Attribute(W.abstractNumId) == a).FirstOrDefault();
|
||||
string numStyleLink = (string)abstractNum.Elements(W.numStyleLink)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
if (numStyleLink != null)
|
||||
{
|
||||
XElement style = styles.Root.Elements(W.style)
|
||||
.Where(e => (string)e.Attribute(W.styleId) == numStyleLink)
|
||||
.FirstOrDefault();
|
||||
XElement numPr = style.Elements(W.pPr).Elements(W.numPr).FirstOrDefault();
|
||||
int lNumId = (int)numPr.Elements(W.numId).Attributes(W.val)
|
||||
.FirstOrDefault();
|
||||
return GetListItemInfoByNumIdAndIlvl(numbering, styles, lNumId, ilvl);
|
||||
}
|
||||
for (int l = ilvl; l >= 0; --l)
|
||||
{
|
||||
listItemInfo.Lvl = abstractNum.Elements(W.lvl)
|
||||
.Where(e => (int)e.Attribute(W.ilvl) == l).FirstOrDefault();
|
||||
if (listItemInfo.Lvl == null)
|
||||
continue;
|
||||
if (listItemInfo.Start == null)
|
||||
listItemInfo.Start = (int?)listItemInfo.Lvl.Elements(W.start)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
return listItemInfo;
|
||||
}
|
||||
return new ListItemInfo(false);
|
||||
}
|
||||
|
||||
private static ListItemInfo GetListItemInfoByNumIdAndStyleId(XDocument numbering,
|
||||
XDocument styles, int numId, string paragraphStyle)
|
||||
{
|
||||
// If you have to find the w:lvl by style id, then we can't find it in the
|
||||
// w:lvlOverride, as that requires that you have determined the level already.
|
||||
ListItemInfo listItemInfo = new ListItemInfo(true);
|
||||
XElement num = numbering.Root.Elements(W.num)
|
||||
.Where(e => (int)e.Attribute(W.numId) == numId).FirstOrDefault();
|
||||
listItemInfo.AbstractNumId = (int)num.Elements(W.abstractNumId)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
int? a = listItemInfo.AbstractNumId;
|
||||
XElement abstractNum = numbering.Root.Elements(W.abstractNum)
|
||||
.Where(e => (int)e.Attribute(W.abstractNumId) == a).FirstOrDefault();
|
||||
string numStyleLink = (string)abstractNum.Element(W.numStyleLink)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
if (numStyleLink != null)
|
||||
{
|
||||
XElement style = styles.Root.Elements(W.style)
|
||||
.Where(e => (string)e.Attribute(W.styleId) == numStyleLink)
|
||||
.FirstOrDefault();
|
||||
XElement numPr = style.Elements(W.pPr).Elements(W.numPr).FirstOrDefault();
|
||||
int lNumId = (int)numPr.Elements(W.numId).Attributes(W.val).FirstOrDefault();
|
||||
return GetListItemInfoByNumIdAndStyleId(numbering, styles, lNumId,
|
||||
paragraphStyle);
|
||||
}
|
||||
listItemInfo.Lvl = abstractNum.Elements(W.lvl)
|
||||
.Where(e => (string)e.Element(W.pStyle) == paragraphStyle).FirstOrDefault();
|
||||
listItemInfo.Start = (int?)listItemInfo.Lvl.Elements(W.start).Attributes(W.val)
|
||||
.FirstOrDefault();
|
||||
return listItemInfo;
|
||||
}
|
||||
|
||||
private static ListItemInfo GetListItemInfo(XDocument numbering, XDocument styles,
|
||||
XElement paragraph)
|
||||
{
|
||||
// The following is an optimization - only determine ListItemInfo once for a
|
||||
// paragraph.
|
||||
ListItemInfo listItemInfo = paragraph.Annotation<ListItemInfo>();
|
||||
if (listItemInfo != null)
|
||||
return listItemInfo;
|
||||
XElement paragraphNumberingProperties = paragraph.Elements(W.pPr)
|
||||
.Elements(W.numPr).FirstOrDefault();
|
||||
string paragraphStyle = (string)paragraph.Elements(W.pPr).Elements(W.pStyle)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
if (paragraphNumberingProperties != null &&
|
||||
paragraphNumberingProperties.Element(W.numId) != null)
|
||||
{
|
||||
// Paragraph numbering properties must contain a numId.
|
||||
int numId = (int)paragraphNumberingProperties.Elements(W.numId)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
int? ilvl = (int?)paragraphNumberingProperties.Elements(W.ilvl)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
if (ilvl != null)
|
||||
{
|
||||
listItemInfo = GetListItemInfoByNumIdAndIlvl(numbering, styles, numId,
|
||||
(int)ilvl);
|
||||
paragraph.AddAnnotation(listItemInfo);
|
||||
return listItemInfo;
|
||||
}
|
||||
if (paragraphStyle != null)
|
||||
{
|
||||
listItemInfo = GetListItemInfoByNumIdAndStyleId(numbering, styles,
|
||||
numId, paragraphStyle);
|
||||
paragraph.AddAnnotation(listItemInfo);
|
||||
return listItemInfo;
|
||||
}
|
||||
listItemInfo = new ListItemInfo(false);
|
||||
paragraph.AddAnnotation(listItemInfo);
|
||||
return listItemInfo;
|
||||
}
|
||||
if (paragraphStyle != null)
|
||||
{
|
||||
XElement style = styles.Root.Elements(W.style).Where(s =>
|
||||
(string)s.Attribute(W.type) == "paragraph" &&
|
||||
(string)s.Attribute(W.styleId) == paragraphStyle).FirstOrDefault();
|
||||
if (style != null)
|
||||
{
|
||||
XElement styleNumberingProperties = style.Elements(W.pPr)
|
||||
.Elements(W.numPr).FirstOrDefault();
|
||||
if (styleNumberingProperties != null &&
|
||||
styleNumberingProperties.Element(W.numId) != null)
|
||||
{
|
||||
int numId = (int)styleNumberingProperties.Elements(W.numId)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
int? ilvl = (int?)styleNumberingProperties.Elements(W.ilvl)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
if (ilvl == null)
|
||||
ilvl = 0;
|
||||
listItemInfo = GetListItemInfoByNumIdAndIlvl(numbering, styles,
|
||||
numId, (int)ilvl);
|
||||
paragraph.AddAnnotation(listItemInfo);
|
||||
return listItemInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
listItemInfo = new ListItemInfo(false);
|
||||
paragraph.AddAnnotation(listItemInfo);
|
||||
return listItemInfo;
|
||||
}
|
||||
|
||||
private static IEnumerable<LevelNumbers> ParagraphsToConsiderWhenCounting(
|
||||
XDocument numbering, XDocument styles, XElement paragraph, int levelNumber)
|
||||
{
|
||||
ListItemInfo listItemInfo = GetListItemInfo(numbering, styles, paragraph);
|
||||
int? lvlRestart = (int?)listItemInfo.Lvl.Elements(W.lvlRestart)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
int paragraphLevel = (int)listItemInfo.Lvl.Attribute(W.ilvl);
|
||||
IEnumerable<XElement> paragraphsBeforeSelf = paragraph
|
||||
.ElementsBeforeSelfReverseDocumentOrder().Where(e => e.Name == W.p);
|
||||
foreach (var p in paragraphsBeforeSelf)
|
||||
{
|
||||
ListItemInfo pListItemInfo = GetListItemInfo(numbering, styles, p);
|
||||
if (!pListItemInfo.IsListItem ||
|
||||
pListItemInfo.AbstractNumId != listItemInfo.AbstractNumId)
|
||||
continue;
|
||||
LevelNumbers pLevelNumbers = p.Annotation<LevelNumbers>();
|
||||
int pLevel = (int)pListItemInfo.Lvl.Attribute(W.ilvl);
|
||||
if (pLevel > levelNumber)
|
||||
yield return pLevelNumbers;
|
||||
if (lvlRestart == null)
|
||||
{
|
||||
if (pLevel < levelNumber)
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pLevel < levelNumber && pLevel > lvlRestart - 1)
|
||||
continue;
|
||||
else if (pLevel < levelNumber)
|
||||
yield break;
|
||||
}
|
||||
yield return pLevelNumbers;
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetLevelNumberForLevel(XDocument numbering, XDocument styles,
|
||||
XElement paragraph, int level)
|
||||
{
|
||||
ListItemInfo listItemInfo = GetListItemInfo(numbering, styles, paragraph);
|
||||
int paragraphLevel = (int)listItemInfo.Lvl.Attribute(W.ilvl);
|
||||
var paragraphsToConsider = ParagraphsToConsiderWhenCounting(numbering, styles,
|
||||
paragraph, level)
|
||||
.Select(o => o.LevelNumbersArray.Take(paragraphLevel + 1)
|
||||
.Select(z => z.ToString() + ".").StringConcatenate())
|
||||
.GroupBy(o => o);
|
||||
int levelNumberForLevel = paragraphsToConsider.Count();
|
||||
return levelNumberForLevel;
|
||||
}
|
||||
|
||||
private static int[] GetLevelNumbers(XDocument numbering, XDocument styles,
|
||||
XElement paragraph)
|
||||
{
|
||||
IEnumerable<XElement> paragraphsBeforeSelf = paragraph
|
||||
.ElementsBeforeSelfReverseDocumentOrder().Where(e => e.Name == W.p);
|
||||
int level;
|
||||
ListItemInfo listItemInfo = GetListItemInfo(numbering, styles, paragraph);
|
||||
level = (int)listItemInfo.Lvl.Attribute(W.ilvl);
|
||||
List<int> levelNumbers = new List<int>();
|
||||
for (int indentationLevel = 0; indentationLevel <= level; ++indentationLevel)
|
||||
{
|
||||
XElement currentIndentLvl = GetRelatedLevel(listItemInfo.Lvl,
|
||||
indentationLevel);
|
||||
int? start = (int?)currentIndentLvl.Elements(W.start).Attributes(W.val)
|
||||
.FirstOrDefault();
|
||||
if (start == null)
|
||||
start = 1;
|
||||
XElement paragraphWithSameAbstractNumId = paragraphsBeforeSelf
|
||||
.FirstOrDefault(p =>
|
||||
{
|
||||
ListItemInfo pListItemInfo = GetListItemInfo(numbering, styles, p);
|
||||
return pListItemInfo.IsListItem &&
|
||||
pListItemInfo.AbstractNumId == listItemInfo.AbstractNumId;
|
||||
});
|
||||
if (paragraphWithSameAbstractNumId != null)
|
||||
{
|
||||
LevelNumbers pLevelNumbers = paragraphWithSameAbstractNumId
|
||||
.Annotation<LevelNumbers>();
|
||||
if (pLevelNumbers.LevelNumbersArray.Length > indentationLevel)
|
||||
{
|
||||
if (indentationLevel == level)
|
||||
levelNumbers.Add(
|
||||
pLevelNumbers.LevelNumbersArray[indentationLevel] + 1);
|
||||
else
|
||||
levelNumbers.Add(pLevelNumbers
|
||||
.LevelNumbersArray[indentationLevel]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (level == indentationLevel)
|
||||
{
|
||||
int c1 = GetLevelNumberForLevel(numbering, styles, paragraph,
|
||||
indentationLevel);
|
||||
int? start2 = listItemInfo.Start;
|
||||
if (start2 == null)
|
||||
start2 = 1;
|
||||
levelNumbers.Add(c1 + (int)start2);
|
||||
continue;
|
||||
}
|
||||
levelNumbers.Add((int)start);
|
||||
}
|
||||
return levelNumbers.ToArray();
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetFormatTokens(string lvlText)
|
||||
{
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
if (i >= lvlText.Length)
|
||||
yield break;
|
||||
if (lvlText[i] == '%' && i <= lvlText.Length - 2)
|
||||
{
|
||||
yield return lvlText.Substring(i, 2);
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
int percentIndex = lvlText.IndexOf('%', i);
|
||||
if (percentIndex == -1 || percentIndex > lvlText.Length - 2)
|
||||
{
|
||||
yield return lvlText.Substring(i);
|
||||
yield break;
|
||||
}
|
||||
yield return lvlText.Substring(i, percentIndex - i);
|
||||
yield return lvlText.Substring(percentIndex, 2);
|
||||
i = percentIndex + 2;
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] RomanOnes =
|
||||
{
|
||||
"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
|
||||
};
|
||||
|
||||
private static string[] RomanTens =
|
||||
{
|
||||
"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"
|
||||
};
|
||||
|
||||
private static string[] RomanHundreds =
|
||||
{
|
||||
"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "M"
|
||||
};
|
||||
|
||||
private static string[] RomanThousands =
|
||||
{
|
||||
"", "M", "MM", "MMM", "MMMM", "MMMMM", "MMMMMM", "MMMMMMM", "MMMMMMMM",
|
||||
"MMMMMMMMM", "MMMMMMMMMM"
|
||||
};
|
||||
|
||||
private static string[] OneThroughNineteen = {
|
||||
"one", "two", "three", "four", "five", "six", "seven", "eight",
|
||||
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
|
||||
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
|
||||
};
|
||||
|
||||
private static string[] Tens = {
|
||||
"ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
|
||||
"eighty", "ninety"
|
||||
};
|
||||
|
||||
private static string[] OrdinalOneThroughNineteen = {
|
||||
"first", "second", "third", "fourth", "fifth", "sixth",
|
||||
"seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth",
|
||||
"thirteenth", "fourteenth", "fifteenth", "sixteenth",
|
||||
"seventeenth", "eighteenth", "nineteenth"
|
||||
};
|
||||
|
||||
private static string[] OrdinalTenths = {
|
||||
"tenth", "twentieth", "thirtieth", "fortieth", "fiftieth",
|
||||
"sixtieth", "seventieth", "eightieth", "ninetieth"
|
||||
};
|
||||
|
||||
private static string GetLevelText(int levelNumber, string numFmt)
|
||||
{
|
||||
if (numFmt == "decimal")
|
||||
{
|
||||
return levelNumber.ToString();
|
||||
}
|
||||
if (numFmt == "decimalZero")
|
||||
{
|
||||
if (levelNumber <= 9)
|
||||
return "0" + levelNumber.ToString();
|
||||
else
|
||||
return levelNumber.ToString();
|
||||
}
|
||||
if (numFmt == "upperRoman")
|
||||
{
|
||||
int ones = levelNumber % 10;
|
||||
int tens = (levelNumber % 100) / 10;
|
||||
int hundreds = (levelNumber % 1000) / 100;
|
||||
int thousands = levelNumber / 1000;
|
||||
return RomanThousands[thousands] + RomanHundreds[hundreds] +
|
||||
RomanTens[tens] + RomanOnes[ones];
|
||||
}
|
||||
if (numFmt == "lowerRoman")
|
||||
{
|
||||
int ones = levelNumber % 10;
|
||||
int tens = (levelNumber % 100) / 10;
|
||||
int hundreds = (levelNumber % 1000) / 100;
|
||||
int thousands = levelNumber / 1000;
|
||||
return (RomanThousands[thousands] + RomanHundreds[hundreds] +
|
||||
RomanTens[tens] + RomanOnes[ones]).ToLower();
|
||||
}
|
||||
if (numFmt == "upperLetter")
|
||||
{
|
||||
string a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
int c = (levelNumber - 1) / 26;
|
||||
int n = (levelNumber - 1) % 26;
|
||||
char x = a[n];
|
||||
return "".PadRight(c + 1, x);
|
||||
}
|
||||
if (numFmt == "lowerLetter")
|
||||
{
|
||||
string a = "abcdefghijklmnopqrstuvwxyz";
|
||||
int c = (levelNumber - 1) / 26;
|
||||
int n = (levelNumber - 1) % 26;
|
||||
char x = a[n];
|
||||
return "".PadRight(c + 1, x);
|
||||
}
|
||||
if (numFmt == "ordinal")
|
||||
{
|
||||
string suffix;
|
||||
if (levelNumber % 100 == 11 || levelNumber % 100 == 12 ||
|
||||
levelNumber % 100 == 13)
|
||||
suffix = "th";
|
||||
else if (levelNumber % 10 == 1)
|
||||
suffix = "st";
|
||||
else if (levelNumber % 10 == 2)
|
||||
suffix = "nd";
|
||||
else if (levelNumber % 10 == 3)
|
||||
suffix = "rd";
|
||||
else
|
||||
suffix = "th";
|
||||
return levelNumber.ToString() + suffix;
|
||||
}
|
||||
if (numFmt == "cardinalText")
|
||||
{
|
||||
string result = "";
|
||||
int t1 = levelNumber / 1000;
|
||||
int t2 = levelNumber % 1000;
|
||||
if (t1 >= 1)
|
||||
result += OneThroughNineteen[t1 - 1] + " thousand";
|
||||
if (t1 >= 1 && t2 == 0)
|
||||
return result.Substring(0, 1).ToUpper() +
|
||||
result.Substring(1);
|
||||
if (t1 >= 1)
|
||||
result += " ";
|
||||
int h1 = (levelNumber % 1000) / 100;
|
||||
int h2 = levelNumber % 100;
|
||||
if (h1 >= 1)
|
||||
result += OneThroughNineteen[h1 - 1] + " hundred";
|
||||
if (h1 >= 1 && h2 == 0)
|
||||
return result.Substring(0, 1).ToUpper() +
|
||||
result.Substring(1);
|
||||
if (h1 >= 1)
|
||||
result += " ";
|
||||
int z = levelNumber % 100;
|
||||
if (z <= 19)
|
||||
result += OneThroughNineteen[z - 1];
|
||||
else
|
||||
{
|
||||
int x = z / 10;
|
||||
int r = z % 10;
|
||||
result += Tens[x - 1];
|
||||
if (r >= 1)
|
||||
result += "-" + OneThroughNineteen[r - 1];
|
||||
}
|
||||
return result.Substring(0, 1).ToUpper() +
|
||||
result.Substring(1);
|
||||
}
|
||||
if (numFmt == "ordinalText")
|
||||
{
|
||||
string result = "";
|
||||
int t1 = levelNumber / 1000;
|
||||
int t2 = levelNumber % 1000;
|
||||
if (t1 >= 1 && t2 != 0)
|
||||
result += OneThroughNineteen[t1 - 1] + " thousand";
|
||||
if (t1 >= 1 && t2 == 0)
|
||||
{
|
||||
result += OneThroughNineteen[t1 - 1] + " thousandth";
|
||||
return result.Substring(0, 1).ToUpper() +
|
||||
result.Substring(1);
|
||||
}
|
||||
if (t1 >= 1)
|
||||
result += " ";
|
||||
int h1 = (levelNumber % 1000) / 100;
|
||||
int h2 = levelNumber % 100;
|
||||
if (h1 >= 1 && h2 != 0)
|
||||
result += OneThroughNineteen[h1 - 1] + " hundred";
|
||||
if (h1 >= 1 && h2 == 0)
|
||||
{
|
||||
result += OneThroughNineteen[h1 - 1] + " hundredth";
|
||||
return result.Substring(0, 1).ToUpper() +
|
||||
result.Substring(1);
|
||||
}
|
||||
if (h1 >= 1)
|
||||
result += " ";
|
||||
int z = levelNumber % 100;
|
||||
if (z <= 19)
|
||||
result += OrdinalOneThroughNineteen[z - 1];
|
||||
else
|
||||
{
|
||||
int x = z / 10;
|
||||
int r = z % 10;
|
||||
if (r == 0)
|
||||
result += OrdinalTenths[x - 1];
|
||||
else
|
||||
result += Tens[x - 1];
|
||||
if (r >= 1)
|
||||
result += "-" + OrdinalOneThroughNineteen[r - 1];
|
||||
}
|
||||
return result.Substring(0, 1).ToUpper() +
|
||||
result.Substring(1);
|
||||
}
|
||||
if (numFmt == "bullet")
|
||||
return "";
|
||||
// This method needs to be enhanced to support all languages and
|
||||
// all number formats.
|
||||
return levelNumber.ToString();
|
||||
}
|
||||
|
||||
private static XElement GetRelatedLevel(XElement lvl, int level)
|
||||
{
|
||||
XElement parent = lvl.Parent;
|
||||
XElement newLvl;
|
||||
if (parent.Name == W.lvlOverride)
|
||||
{
|
||||
newLvl = parent.Parent.Elements(W.lvlOverride).Elements(W.lvl)
|
||||
.Where(e => (int)e.Attribute(W.ilvl) == level).FirstOrDefault();
|
||||
if (newLvl != null)
|
||||
return newLvl;
|
||||
int abstractNumId = (int)parent.Parent.Elements(W.abstractNumId)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
XElement abstractNum = lvl.Ancestors().Last().Elements(W.abstractNum)
|
||||
.Where(e => (int)e.Attribute(W.abstractNumId) == abstractNumId)
|
||||
.FirstOrDefault();
|
||||
newLvl = abstractNum.Elements(W.lvl)
|
||||
.Where(e => (int)e.Attribute(W.ilvl) == level).FirstOrDefault();
|
||||
return newLvl;
|
||||
}
|
||||
newLvl = parent.Elements(W.lvl).Where(e => (int)e.Attribute(W.ilvl) == level)
|
||||
.FirstOrDefault();
|
||||
return newLvl;
|
||||
}
|
||||
|
||||
private static string FormatListItem(XElement lvl, int[] levelNumbers,
|
||||
string lvlText, string bulletReplacementString)
|
||||
{
|
||||
if (bulletReplacementString != null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(lvlText);
|
||||
sb.Replace("\xF076", bulletReplacementString);
|
||||
sb.Replace("\xF0D8", bulletReplacementString);
|
||||
sb.Replace("\xF0A7", bulletReplacementString);
|
||||
sb.Replace("\xF0B7", bulletReplacementString);
|
||||
sb.Replace("\xF0A8", bulletReplacementString);
|
||||
sb.Replace("\xF0FC", bulletReplacementString);
|
||||
lvlText = sb.ToString();
|
||||
}
|
||||
string[] formatTokens = GetFormatTokens(lvlText).ToArray();
|
||||
bool isLgl = lvl.Elements(W.isLgl).Any();
|
||||
string listItem = formatTokens.Select((t, l) =>
|
||||
{
|
||||
if (t.Substring(0, 1) != "%")
|
||||
return t;
|
||||
int indentationLevel = Int32.Parse(t.Substring(1)) - 1;
|
||||
int levelNumber = levelNumbers[indentationLevel];
|
||||
string levelText;
|
||||
XElement rlvl = GetRelatedLevel(lvl, indentationLevel);
|
||||
string numFmtForLevel = (string)rlvl.Elements(W.numFmt).Attributes(W.val)
|
||||
.FirstOrDefault();
|
||||
if (isLgl && numFmtForLevel != "decimalZero")
|
||||
numFmtForLevel = "decimal";
|
||||
levelText = GetLevelText(levelNumber, numFmtForLevel);
|
||||
return levelText;
|
||||
}).StringConcatenate();
|
||||
return listItem + " ";
|
||||
}
|
||||
|
||||
public static string RetrieveListItem(WmlDocument document,
|
||||
XElement paragraph, string bulletReplacementString)
|
||||
{
|
||||
using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(document))
|
||||
{
|
||||
using (WordprocessingDocument wdoc = streamDoc.GetWordprocessingDocument())
|
||||
{
|
||||
return RetrieveListItem(wdoc, paragraph, bulletReplacementString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string RetrieveListItem(WordprocessingDocument wordDoc,
|
||||
XElement paragraph, string bulletReplacementString)
|
||||
{
|
||||
string pt = paragraph.Elements(W.r).Elements(W.t).Select(e => e.Value)
|
||||
.StringConcatenate();
|
||||
NumberingDefinitionsPart numberingDefinitionsPart =
|
||||
wordDoc.MainDocumentPart.NumberingDefinitionsPart;
|
||||
if (numberingDefinitionsPart == null)
|
||||
return null;
|
||||
StyleDefinitionsPart styleDefinitionsPart = wordDoc.MainDocumentPart
|
||||
.StyleDefinitionsPart;
|
||||
if (styleDefinitionsPart == null)
|
||||
return null;
|
||||
XDocument numbering = numberingDefinitionsPart.GetXDocument();
|
||||
XDocument styles = styleDefinitionsPart.GetXDocument();
|
||||
ListItemInfo listItemInfo = GetListItemInfo(numbering, styles, paragraph);
|
||||
if (listItemInfo.IsListItem)
|
||||
{
|
||||
string lvlText = (string)listItemInfo.Lvl.Elements(W.lvlText)
|
||||
.Attributes(W.val).FirstOrDefault();
|
||||
int[] levelNumbers = GetLevelNumbers(numbering, styles, paragraph);
|
||||
paragraph.AddAnnotation(new LevelNumbers()
|
||||
{
|
||||
LevelNumbersArray = levelNumbers
|
||||
});
|
||||
string listItem = FormatListItem(listItemInfo.Lvl, levelNumbers, lvlText,
|
||||
bulletReplacementString);
|
||||
return listItem;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user