Ra3.BattleNet.Metadata 是一个 XML 元数据处理和解析库,用于管理客户端元数据、模组信息、版本包和更新日志等。
using Ra3.BattleNet.Metadata;var metadata = Metadata.LoadFromFile("./Metadata/metadata.xml");var metadata = Metadata.LoadFromFile("./Metadata/metadata.xml");
// 方式A:直接扩展方法
foreach (var mod in metadata.Mods())
{
Console.WriteLine($"{mod.Id} -> {mod.Version}");
}
var corona = metadata.Mods().FirstOrDefault(m => m.Id == "Corona");
Console.WriteLine(corona?.Version); // 3.229
// 方式B:Catalog 入口(更像“数据仓库”)
var catalog = metadata.Catalog();
var app = catalog.Application("RA3BattleNet");
Console.WriteLine(app?.Version); // 1.5.2.0// 方法1:直接通过 ID 查找 Markdown 元素(推荐)
var changelogMarkdown = metadata.GetElementById("changelog-zh-1.5.2.0");
if (changelogMarkdown != null)
{
var source = changelogMarkdown.Get("Source"); // zh-1.5.2.0.md
var hash = changelogMarkdown.Get("Hash"); // MD5 哈希值
Console.WriteLine($"文件: {source}, 哈希: {hash}");
}
// 方法2:通过 Corona 模组遍历所有版本的 Changelog
var corona = metadata.GetElementById("Corona");
if (corona != null)
{
var currentVersion = corona.Get("CurrentVersion");
var packages = corona.Find("Packages");
foreach (var package in packages.Children.Where(c => c.Name == "Package"))
{
var version = package.Get("Version");
var changelogs = package.Find("Changelogs");
foreach (var changelog in changelogs.Children.Where(c => c.Name == "Changelog"))
{
var language = changelog.Get("Language");
// Changelog 的 ID 存储在子元素的名称中
var changelogId = changelog.Children.FirstOrDefault()?.Name;
// 通过 ID 查找对应的 Markdown 文件
var md = metadata.GetElementById(changelogId);
if (md != null)
{
var mdSource = md.Get("Source");
Console.WriteLine($"{version} - {language}: {mdSource}");
}
}
}
}var allMarkdowns = metadata.GetAllElements("Markdown");
var changelogMarkdowns = allMarkdowns.Where(m =>
m.Get("ID")?.StartsWith("changelog-") == true
).ToList();
foreach (var md in changelogMarkdowns)
{
Console.WriteLine($"{md.Get("ID")}: {md.Get("Source")}");
}var tree = metadata.GetIncludeTree();
Console.WriteLine(tree);
// 输出示例:
// Metadata
// Tags
// Includes
// Metadata
// corona [private]
// Corona按 ID 查找元素,支持 public/private 访问控制。
var element = metadata.GetElementById("Corona");按路径查找元素,使用 : 分隔。
var element = metadata.Find("Includes:Metadata:Corona");获取所有指定名称的元素。
var allPackages = metadata.GetAllElements("Package");获取元素的属性值。
var version = element.Get("Version");
var versionWithDefault = element.Get("Version", "1.0.0");获取所有属性的只读字典。
foreach (var attr in element.Variables)
{
Console.WriteLine($"{attr.Key}: {attr.Value}");
}获取所有子元素。
foreach (var child in element.Children)
{
Console.WriteLine(child.Name);
}获取父元素。
var parent = element.Parent;获取 Include 类型("public" 或 "private")。
if (element.IncludeType == "private")
{
Console.WriteLine("这是私有 Include");
}获取元素的完整路径。
var path = element.GetElementPath();
// 输出: Metadata -> Includes -> Metadata -> Corona获取 Include 引用树的可视化表示。
var tree = metadata.GetIncludeTree();
Console.WriteLine(tree);<Metadata>
<Tags>
<Commit>${ENV:CF_PAGES_COMMIT_SHA}</Commit>
</Tags>
<Includes>
<Include Source="mods/mods.xml" Type="public" />
</Includes>
</Metadata>- Type="public": Include 的元素对父节点可见
- Type="private": Include 的元素只在子树中可见(默认)
支持以下变量语法:
${ENV:变量名}- 系统环境变量${MD5::}- 当前文件的 MD5 哈希${MD5:文件名}- 指定文件的 MD5 哈希${META:路径}- 元数据引用${this:变量}- 当前模块内引用
Metadata (根)
└── Includes
├── Metadata (apps)
│ └── RA3BattleNet (ID="RA3BattleNet")
│ ├── Packages
│ │ └── Package (Version="1.5.2.0")
│ │ └── Changelogs
│ │ └── Changelog (Language="zh-CN")
│ └── Posts
└── Metadata (mods)
└── Corona (ID="Corona")
├── Packages
│ └── Package (Version="3.229")
│ └── Changelogs
│ └── Changelog (Language="zh-CN")
└── Posts
- Markdown 元素有
ID属性,可以直接通过GetElementById()查找 - Changelog 元素的 ID 存储在其子元素的名称中,不是属性
- private Include 的元素只在子树中可见
- public Include 的元素对父节点也可见
dotnet build Ra3.BattleNet.Metadata/Ra3.BattleNet.Metadata.csprojdotnet run --project Ra3.BattleNet.Metadata --src="./Metadata" --dst="./Output"主程序会:
- 加载 metadata.xml
- 替换环境变量和计算 MD5 哈希
- 复制所有文件到输出目录
- 验证处理后的元数据
- 显示 Include 引用树
dotnet test Ra3.BattleNet.Metadata.Tests/Ra3.BattleNet.Metadata.Tests.csproj- XML 元数据解析和验证
- 循环引用检测
- Include 引用关系树(支持 public/private 访问控制)
- 变量替换系统(ENV、MD5、META、this)
- 资源验证和 MD5 哈希计算
- 丰富的查询 API
- 单元测试覆盖
- XSD Schema 验证
- 详细的错误位置信息(行号、XPath)
- 增量编译支持
运行主程序后的输出:
工作目录: F:\RA3BattleNet\Metadata
元数据源目录: ./Metadata
输出目录: ./Output
加载元数据: ./Metadata\metadata.xml
✓ 成功加载元数据(2 个子节点)
替换环境变量和计算哈希...
✓ 变量替换完成
复制文件到输出目录...
已复制 15 个文件
✓ 文件复制完成
验证处理后的元数据...
✓ 验证成功
=== 元数据信息 ===
根节点: Metadata
子节点数: 2
=== Include 引用树 ===
Metadata
Tags
Includes
Metadata
corona [private]
Corona
RA3BattleNet
...
处理完成!