replace 实际替换什么#

XML 没有“替换第 15 行”这样的操作,换行只是排版。替换范围由 sel 选择器决定。每个 replace 操作必须恰好选择一个节点。多个目标应分别使用独立操作。

选择目标 被替换的内容 保留的内容
/items/item[@id='a']/@enabled enabled 属性值 其他属性和子节点
/items/item[@id='a']/label/text() label 内的文本节点 label 元素及其属性
/items/item[@id='a'] 整个 item 元素 同级元素;选中 item 的旧属性和子节点会被移除
/items 根元素及其内容 仅保留选中根元素以外的内容;这是大范围替换

diff 是加载时执行的 XML 操作列表,replace 是其中一种操作。通过 subst_ 整体替代文件是另一种机制。扩展中出现同名文件并不意味着完全替换,数据表可能会合并条目。参见 ext_、subst_ 和散装文件.

原始教学文档#

这些是虚构数据。下方每个示例都单独应用于原始文档,而不是接着上一个示例执行。示例用于解释结构,并未单独在游戏中运行。

XML
<items version="1">
  <item id="a" enabled="false">
    <label lang="en">Old name</label>
    <price min="10" max="20" />
  </item>
  <item id="b" />
</items>

仅替换属性#

XML
<diff>
  <replace sel="/items/item[@id='a']/@enabled">true</replace>
</diff>

结果:enabled 变为 true;label、price、其他属性和 item b 保持不变。该属性必须已存在。要添加新属性,请使用带 type="@name" 的 add。

替换元素内的文本#

XML
<diff>
  <replace sel="/items/item[@id='a']/label/text()">New name</replace>
</diff>

结果:label 包含 New name,并保留 lang="en"。这会替换选中的整个文本节点,而不是其中的子字符串。空元素可能没有文本节点,混合内容可能有多个文本节点。请检查是否恰好匹配一个节点。

替换元素及其所有子节点#

XML
<diff>
  <replace sel="/items/item[@id='a']">
    <item id="a" enabled="true">
      <label lang="en">New name</label>
    </item>
  </replace>
</diff>

预期文档:

XML
<items version="1">
  <item id="a" enabled="true">
    <label lang="en">New name</label>
  </item>
  <item id="b" />
</items>

price 已被移除,因为新的 item 不包含它。旧子节点不会自动保留。这种替换还可能清除其他模组在所选元素内部的修改。

替换根元素#

XML
<diff>
  <replace sel="/items">
    <items version="2">
      <item id="c" />
    </items>
  </replace>
</diff>

预期文档:

XML
<items version="2">
  <item id="c" />
</items>

旧 item a 和 b 随旧根元素一起被移除。这替换的是处理中文档的 XML 树,不是文件原始字节,也不会覆盖磁盘上的原文件。只改一个值时应选择更小的目标;替换根元素需要提供全部必要数据并检查冲突。

对照真实 X4 文件检查#

补丁相对于扩展的路径决定目标文件。读取当前版本的数据,找到稳定 ID,并确认恰好匹配一个节点。操作从上到下执行,后面的操作会看到前面操作的结果。

零匹配表示未找到目标。多个匹配不表示批量替换。silent 只会抑制消息,不会修复选择器。选择器语言受到限制,请核对当前安装中的 diff.xsd 模式。

比较最终生效的 XML,然后单独检查游戏效果和日志。上述示例不是 X4 加载器模拟器。继续阅读 结合使用 add、replace 和 remove, 舰船补丁 和 互动性.