以下 Open XML 标记表示您的“出生日期:2019 年 10 月 15 日”行,其中“th”格式为上标:
<w:p>
<w:r>
<w:t>Date of birth: October 15</w:t>
</w:r>
<w:r>
<w:rPr>
<w:vertAlign w:val="superscript"/>
</w:rPr>
<w:t>th</w:t>
</w:r>
<w:r>
<w:t>, 2019</w:t>
</w:r>
</w:p>
注意第二个w:r 元素(Run 类)及其w:rPr 子元素(RunProperties 类)和w:vertAlign 孙子元素(VerticalTextAlignment 类),它将“th”格式化为上标。
使用 Open XML SDK,您将创建上述段落,如下所示(注意缩进匹配,因此您可以看到对应关系):
var paragraph =
new Paragraph(
new Run(
new Text("Date of birth: October 15")),
new Run(
new RunProperties(
new VerticalTextAlignment { Val = VerticalPositionValues.Superscript }),
new Text("th")),
new Run(
new Text(", 2019")));
2019 年 11 月 25 日更新:
如果您想格式化现有文本,如上所示,您必须识别和格式化序数足以“st”、“nd”、“rd”和“th”。 Paragraph FormatSuperscript(string innerText) 方法可以做到这一点。它使用Text CreateText(string text) 方法为您要呈现的任何文本(即没有前导或尾随空格)生成具有正确xml:space 属性的w:text 元素。
// Matches ordinal number suffixes "st", "nd", "rd", and "th".
private static readonly Regex OrdinalNumberSuffixRegex =
new Regex("(?<=[0-9]+)(st|nd|rd|th)");
/// <summary>
/// Creates a new <see cref="Paragraph" /> with ordinal number suffixes
/// (i.e., "st", "nd", "rd", and "4th") formatted as a superscript.
/// </summary>
/// <param name="innerText">The paragraph's inner text.</param>
/// <returns>A new, formatted <see cref="Paragraph" />.</returns>
public static Paragraph FormatSuperscript(string innerText)
{
var destParagraph = new Paragraph();
var startIndex = 0;
foreach (Match match in OrdinalNumberSuffixRegex.Matches(innerText))
{
if (match.Index > startIndex)
{
string text = innerText[startIndex..match.Index];
destParagraph.AppendChild(new Run(CreateText(text)));
}
destParagraph.AppendChild(
new Run(
new RunProperties(
new VerticalTextAlignment
{
Val = VerticalPositionValues.Superscript
}),
CreateText(match.Value)));
startIndex = match.Index + match.Length;
}
if (startIndex < innerText.Length)
{
string text = innerText.Substring(startIndex);
destParagraph.AppendChild(new Run(CreateText(text)));
}
return destParagraph;
}
/// <summary>
/// Creates a new <see cref="Text" /> instance with the correct xml:space
/// attribute value.
/// </summary>
/// <param name="text">The text.</param>
/// <returns>A new <see cref="Text" /> instance.</returns>
public static Text CreateText(string text)
{
if (string.IsNullOrEmpty(text))
{
return new Text();
}
if (char.IsWhiteSpace(text[0]) || char.IsWhiteSpace(text[^1]))
{
return new Text(text) { Space = SpaceProcessingModeValues.Preserve };
}
return new Text(text);
}
以下单元测试展示了如何使用上面的FormatSuperscript() 方法:
[Fact]
public void FormatSuperscript_DateOfBirth_CorrectlyFormatted()
{
// Say we have a body or other container with a number of paragraphs, one
// of which is the paragraph that we want to format. In our case, we want
// the paragraph the inner text of which starts with "Date of birth:"
var body =
new Body(
new Paragraph(new Run(new Text("Full name: Phung Anh Tu"))),
new Paragraph(new Run(new Text("Date of birth: October 15th, 2019"))),
new Paragraph(new Run(new Text("Gender: male"))));
Paragraph sourceParagraph = body
.Descendants<Paragraph>()
.First(p => p.InnerText.StartsWith("Date of birth:"));
// In a first step, we'll create a new, formatted paragraph.
Paragraph destParagraph = FormatSuperscript(sourceParagraph.InnerText);
// Next, we format the existing paragraph by replacing it with the new,
// formatted one.
body.ReplaceChild(destParagraph, sourceParagraph);
// Finally, let's verify that we have a single "th" run that is:
// - preceded by one run with inner text "Date of birth: October 15",
// - followed by one run with inner text ", 2019", and
// - formatted as a superscript.
Assert.Single(body
.Descendants<Run>()
.Where(r => r.InnerText == "th" &&
r.PreviousSibling().InnerText == "Date of birth: October 15" &&
r.NextSibling().InnerText == ", 2019" &&
r.RunProperties.VerticalTextAlignment.Val == VerticalPositionValues.Superscript));
}
您可以在我的CodeSnippets GitHub 存储库中找到完整的源代码。查找OrdinalNumberFormattingTests 类。