169 lines
5.9 KiB
C#
169 lines
5.9 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Text.RegularExpressions;
|
|||
|
|
using DocumentFormat.OpenXml.Packaging;
|
|||
|
|
using DocumentFormat.OpenXml.Wordprocessing;
|
|||
|
|
using Furion.DependencyInjection;
|
|||
|
|
|
|||
|
|
namespace YD_Event.Core.Certificate
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// DOCX模板解析器
|
|||
|
|
/// </summary>
|
|||
|
|
public class DocxTemplateParser : ITransient
|
|||
|
|
{
|
|||
|
|
private const string PlaceholderPattern = @"\{\{([^}]+)\}\}";
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 从DOCX文件中提取占位符
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="docxStream">DOCX文件流</param>
|
|||
|
|
/// <returns>占位符列表</returns>
|
|||
|
|
public List<string> ExtractPlaceholders(Stream docxStream)
|
|||
|
|
{
|
|||
|
|
var placeholders = new HashSet<string>();
|
|||
|
|
|
|||
|
|
using (var document = WordprocessingDocument.Open(docxStream, false))
|
|||
|
|
{
|
|||
|
|
var body = document.MainDocumentPart?.Document?.Body;
|
|||
|
|
if (body == null) return new List<string>();
|
|||
|
|
|
|||
|
|
// 解析段落中的占位符
|
|||
|
|
foreach (var paragraph in body.Elements<Paragraph>())
|
|||
|
|
{
|
|||
|
|
var text = ExtractTextFromParagraph(paragraph);
|
|||
|
|
var foundPlaceholders = ExtractPlaceholdersFromText(text);
|
|||
|
|
foreach (var placeholder in foundPlaceholders)
|
|||
|
|
{
|
|||
|
|
placeholders.Add(placeholder);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析表格中的占位符
|
|||
|
|
foreach (var table in body.Elements<Table>())
|
|||
|
|
{
|
|||
|
|
var tablePlaceholders = ExtractPlaceholdersFromTable(table);
|
|||
|
|
foreach (var placeholder in tablePlaceholders)
|
|||
|
|
{
|
|||
|
|
placeholders.Add(placeholder);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析页眉页脚中的占位符
|
|||
|
|
ExtractPlaceholdersFromHeaderFooter(document, placeholders);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return placeholders.OrderBy(x => x).ToList();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 从文本中提取占位符
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="text">文本内容</param>
|
|||
|
|
/// <returns>占位符列表</returns>
|
|||
|
|
private List<string> ExtractPlaceholdersFromText(string text)
|
|||
|
|
{
|
|||
|
|
var placeholders = new List<string>();
|
|||
|
|
var matches = Regex.Matches(text, PlaceholderPattern);
|
|||
|
|
|
|||
|
|
foreach (Match match in matches)
|
|||
|
|
{
|
|||
|
|
var placeholder = match.Groups[1].Value.Trim();
|
|||
|
|
if (!string.IsNullOrWhiteSpace(placeholder))
|
|||
|
|
{
|
|||
|
|
placeholders.Add(placeholder);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return placeholders;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 从段落中提取文本
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="paragraph">段落元素</param>
|
|||
|
|
/// <returns>文本内容</returns>
|
|||
|
|
private string ExtractTextFromParagraph(Paragraph paragraph)
|
|||
|
|
{
|
|||
|
|
return string.Join("", paragraph.Elements<Run>().Select(run =>
|
|||
|
|
string.Join("", run.Elements<Text>().Select(text => text.Text))));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 从表格中提取占位符
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="table">表格元素</param>
|
|||
|
|
/// <returns>占位符列表</returns>
|
|||
|
|
private List<string> ExtractPlaceholdersFromTable(Table table)
|
|||
|
|
{
|
|||
|
|
var placeholders = new HashSet<string>();
|
|||
|
|
|
|||
|
|
foreach (var row in table.Elements<TableRow>())
|
|||
|
|
{
|
|||
|
|
foreach (var cell in row.Elements<TableCell>())
|
|||
|
|
{
|
|||
|
|
foreach (var paragraph in cell.Elements<Paragraph>())
|
|||
|
|
{
|
|||
|
|
var text = ExtractTextFromParagraph(paragraph);
|
|||
|
|
var cellPlaceholders = ExtractPlaceholdersFromText(text);
|
|||
|
|
foreach (var placeholder in cellPlaceholders)
|
|||
|
|
{
|
|||
|
|
placeholders.Add(placeholder);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return placeholders.ToList();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 从页眉页脚中提取占位符
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="document">Word文档对象</param>
|
|||
|
|
/// <param name="placeholders">占位符集合</param>
|
|||
|
|
private void ExtractPlaceholdersFromHeaderFooter(WordprocessingDocument document, HashSet<string> placeholders)
|
|||
|
|
{
|
|||
|
|
// 暂时跳过页眉页脚处理,因为API兼容性问题
|
|||
|
|
// 实际项目中需要根据具体的DocumentFormat.OpenXml版本调整
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 验证占位符格式
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="placeholder">占位符</param>
|
|||
|
|
/// <returns>是否有效</returns>
|
|||
|
|
public bool IsValidPlaceholder(string placeholder)
|
|||
|
|
{
|
|||
|
|
return !string.IsNullOrWhiteSpace(placeholder) &&
|
|||
|
|
Regex.IsMatch(placeholder, @"^[a-zA-Z_][a-zA-Z0-9_]*$");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取占位符类型
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="placeholder">占位符</param>
|
|||
|
|
/// <returns>占位符类型</returns>
|
|||
|
|
public string GetPlaceholderType(string placeholder)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrWhiteSpace(placeholder))
|
|||
|
|
return "Text";
|
|||
|
|
|
|||
|
|
var lowerPlaceholder = placeholder.ToLowerInvariant();
|
|||
|
|
|
|||
|
|
if (lowerPlaceholder.Contains("date") || lowerPlaceholder.Contains("time"))
|
|||
|
|
return "Date";
|
|||
|
|
|
|||
|
|
if (lowerPlaceholder.Contains("qr") || lowerPlaceholder.Contains("qrcode"))
|
|||
|
|
return "QRCode";
|
|||
|
|
|
|||
|
|
if (lowerPlaceholder.Contains("image") || lowerPlaceholder.Contains("img") || lowerPlaceholder.Contains("photo"))
|
|||
|
|
return "Image";
|
|||
|
|
|
|||
|
|
return "Text";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|