fix: 内置 Office 技能离线资源与中文校验 / offline Office schemas and XML validation (#218)

## 中文

内网环境显式使用 Office skill 校验含 `docProps/core.xml` 的文件时,Schema 仍引用远程 Dublin
Core XSD;Windows 默认 GBK 读取中文 UTF-8 XML 也会报错。本修改让 docx/pptx/xlsx 独立携带完整本地
Schema 闭包,并按 XML 编码声明读取文件,保留完整校验。

- 三个 Office skill 分别随包加入 Dublin Core 三份 XSD,复用本地
xml.xsd,补齐来源、原始摘要、许可与适配说明。
- 修正两个 Microsoft XSD 的 ST_String 类型引用,以及 presentation-forge 编辑器脚本路径。
- 市场版本 1.5.11;docx 1.0.4、pptx 1.0.5、xlsx 1.0.4、presentation-forge
0.1.1,同步目录元数据。
- 新增定向回归:遍历所有内置技能的 XSD,拒绝远程依赖并离线编译;模拟 GBK 校验中文 XML,确认非法 Word 节点仍被拒绝。

验证:126 份 XSD 离线编译、2 项回归通过;i18n/catalog 校验均为 0 errors / 105 既有
warnings;translate --check 与 git diff --check 通过。README
两种语言同步。工作树、路径、Git 元数据与发布正文隐私检查通过。

Windows x64 dev 10.0.181 已通过产品 prepare-static 准备随包依赖,并真实调用
Skill(docx):创建、全校验、解包编辑、重新打包、再全校验均退出 0,两次校验各 18 valid / 0 skipped / 0
errors。该实验禁用 pip/npm 依赖索引,保留模型连接;不等同于正式包或全机断网验收。辅助 Grep
有一次旧参数错误,改正后成功;Python 缓存污染安装摘要另列真机测试跟踪。主仓 market.zip 尚未刷新,源 PR 合并后需通过
sync-market 纳入产品。

## English

Office validation in an intranet deployment still depended on remote
Dublin Core schemas, and reading Chinese UTF-8 XML with the Windows GBK
default could fail. Each Office skill now includes its local schema
dependency closure, and validators read XML as bytes so its declared
encoding is respected without weakening validation.

This also fixes two Microsoft schema type references and the
presentation-forge editor script path. Market version becomes 1.5.11;
skill versions become docx 1.0.4, pptx 1.0.5, xlsx 1.0.4 and
presentation-forge 0.1.1. Vendored schemas include attribution,
licensing, original hashes and adaptation notes.

Validation: 126 schemas compile offline; both targeted regression tests
pass, including GBK input and invalid-node rejection. Catalog/i18n
checks pass with 105 existing warnings each; translation freshness and
whitespace checks pass. Bilingual README and publication privacy checks
are complete.

The actual Windows x64 dev session passed explicit docx loading,
creation, full validation, editing, repacking and revalidation using
product-prepared dependencies. Dependency indexes were disabled while
model connectivity remained available. Packaged/cross-platform testing
and the observed Python-cache installation-digest drift remain
follow-ups. The product bootstrap ZIP will require sync-market after
this source PR merges.

真机测试与剩余验收 / Hardware testing and remaining acceptance:
https://github.com/desirecore/desirecore/issues/4819

---------

Co-authored-by: Johnson <yeslee1126@gmail.com>
This commit is contained in:
2026-10-16 00:06:24 +08:00
committed by GitHub
parent e8fb262399
commit f7f4fcd035
39 changed files with 1846 additions and 44 deletions

View File

@@ -214,6 +214,9 @@ uv run scripts/i18n/test_validate_i18n.py
uv run scripts/catalog/test_validate_catalog_metadata.py
uv run scripts/catalog/test_collection_generator.py
uv run scripts/catalog/test_check_upstream_health.py
# Compile bundled Office schemas offline and validate Chinese XML with a GBK default.
uv run scripts/office/test_offline_resources.py
```
Passing a skill path narrows skill-body validation, but market-level and sidecar checks still run. Choose the relevant test file for your change rather than treating every documentation edit as a reason to run all test suites.

View File

@@ -214,6 +214,9 @@ uv run scripts/i18n/test_validate_i18n.py
uv run scripts/catalog/test_validate_catalog_metadata.py
uv run scripts/catalog/test_collection_generator.py
uv run scripts/catalog/test_check_upstream_health.py
# 离线编译内置 Office Schema,并验证 GBK 默认环境中的中文 XML。
uv run scripts/office/test_offline_resources.py
```
传入技能路径只缩小技能正文的校验范围,市场级与 sidecar 检查仍会执行。应根据改动选择相关测试文件,而不是每次修改文档都运行全部测试。

View File

@@ -23,6 +23,18 @@ required NOTICE attribution apply to those skills.
Upstream: https://github.com/anthropics/skills
## Dublin Core XML schemas
Office core-property validation includes DCMI XML schemas in the `docx`, `pptx`,
and `xlsx` skills. XML schemas Copyright © 2011 [DCMI](https://www.dublincore.org/),
licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
See the [DCMI Schema Use Notice](https://www.dublincore.org/about/copyright/).
Original authors and annotations are retained; imports are adapted to local paths
for offline use. Each skill includes a `scripts/office/schemas/NOTICE.md` with the
original URLs, source digests, and adaptation details, so attribution also travels
with an independently installed skill.
## External / pointer skills
Skills described only by an `entry.json` pointer (no vendored source) are

View File

@@ -0,0 +1,120 @@
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.10"
# dependencies = ["lxml>=5.3,<7", "defusedxml>=0.7"]
# ///
"""内置 Office 技能的离线 Schema 与中文 XML 回归,不访问网络。"""
from __future__ import annotations
import builtins
import importlib.util
import json
import sys
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
from urllib.parse import urlsplit
from lxml import etree
ROOT = Path(__file__).resolve().parents[2]
OFFICE_SKILLS = ("docx", "pptx", "xlsx")
XSD = "{http://www.w3.org/2001/XMLSchema}"
WORD_XML = '''<?xml version="1.0" encoding="UTF-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body><w:p><w:r><w:t>离线中文文档</w:t></w:r></w:p></w:body>
</w:document>'''
CORE_XML = '''<?xml version="1.0" encoding="UTF-8"?>
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dc:title>离线中文文档</dc:title>
<dcterms:created xsi:type="dcterms:W3CDTF">2026-10-14T00:00:00Z</dcterms:created>
</cp:coreProperties>'''
class RejectRemoteSchema(etree.Resolver):
def resolve(self, url, public_id, context):
if urlsplit(url).scheme not in ("", "file") and not Path(url).is_absolute():
raise OSError(f"离线 Schema 不允许远程依赖:{url}")
return None
def offline_parser():
parser = etree.XMLParser(no_network=True)
parser.resolvers.add(RejectRemoteSchema())
return parser
def load_docx_validator(skill: str):
directory = ROOT / "skills" / skill / "scripts" / "office" / "validators"
name = f"market_office_{skill}_validators"
spec = importlib.util.spec_from_file_location(
name, directory / "__init__.py", submodule_search_locations=[str(directory)]
)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module.DOCXSchemaValidator
class OfflineOfficeResourcesTests(unittest.TestCase):
def test_all_builtin_schemas_have_local_dependencies_and_compile_offline(self):
builtin_ids = json.loads((ROOT / "builtin-skills.json").read_text(encoding="utf-8"))["skills"]
checked = 0
for skill in builtin_ids:
skill_root = ROOT / "skills" / skill
for schema in sorted(skill_root.rglob("*.xsd")):
with self.subTest(schema=str(schema.relative_to(ROOT))):
document = etree.parse(str(schema), offline_parser())
for node in document.iter():
if node.tag not in (XSD + "import", XSD + "include", XSD + "redefine"):
continue
location = node.get("schemaLocation")
if location is None:
continue
self.assertEqual(urlsplit(location).scheme, "", location)
target = (schema.parent / location).resolve()
self.assertTrue(target.is_relative_to(skill_root.resolve()), location)
self.assertTrue(target.is_file(), location)
etree.XMLSchema(document)
checked += 1
self.assertGreater(checked, 0, "不能在未发现任何 Schema 时静默通过")
def test_chinese_document_and_dublin_core_validate_with_gbk_default(self):
# 模拟 Windows GBK 默认文本读取,避免只在 UTF-8 的 CI 上掩盖回归。
original_open = builtins.open
def gbk_open(file, mode="r", *args, **kwargs):
if "b" not in mode and not args and "encoding" not in kwargs:
kwargs["encoding"] = "gbk"
return original_open(file, mode, *args, **kwargs)
for skill in OFFICE_SKILLS:
with self.subTest(skill=skill), tempfile.TemporaryDirectory() as temporary:
directory = Path(temporary)
word = directory / "word" / "document.xml"
core = directory / "docProps" / "core.xml"
word.parent.mkdir()
core.parent.mkdir()
word.write_bytes(WORD_XML.encode("utf-8"))
core.write_bytes(CORE_XML.encode("utf-8"))
validator = load_docx_validator(skill)(directory)
with patch("builtins.open", side_effect=gbk_open):
for file in (word, core):
valid, errors = validator._validate_single_file_xsd(file, directory)
self.assertTrue(valid, errors)
# 保留真实 XSD 校验,不能用跳过/放宽校验来实现“通过”。
word.write_bytes(WORD_XML.replace("<w:p>", "<w:unknown>").replace("</w:p>", "</w:unknown>").encode("utf-8"))
valid, errors = validator._validate_single_file_xsd(word, directory)
self.assertFalse(valid)
self.assertTrue(errors)
if __name__ == "__main__":
unittest.main()

View File

@@ -14,7 +14,7 @@ description: >-
PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document
generation. Use when 用户提到 Word文档、docx、创建文档、编辑文档、报告、
备忘录、公文、合同、信函模板。
version: 1.0.3
version: 1.0.4
type: procedural
risk_level: low
status: enabled
@@ -26,7 +26,7 @@ tags:
- office
metadata:
author: anthropic
updated_at: '2026-06-02'
updated_at: '2026-10-14'
i18n:
default_locale: en-US
source_locale: zh-CN

View File

@@ -29,14 +29,14 @@
},
"release": {
"state": "known",
"version": "1.0.3",
"version": "1.0.4",
"versionScheme": "semver"
},
"timestamps": {
"catalogUpdatedAt": {
"state": "known",
"value": "2026-06-04T03:14:36Z",
"precision": "second"
"value": "2026-10-14",
"precision": "day"
},
"releasePublishedAt": {
"state": "unknown"

View File

@@ -0,0 +1,13 @@
# Office 离线 Schema 依赖
此目录包含 Office 元数据校验所需的 Dublin Core XML Schema。XML schemas Copyright © 2011 [DCMI](https://www.dublincore.org/),按 [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) 使用;许可依据见 [DCMI Schema Use Notice](https://www.dublincore.org/about/copyright/)。上游 Schema 标注创建日期为 2003-04-02,原作者与文档注释保留在文件内。
|本地文件|原始来源|原始文件 SHA-256|
|---|---|---|
|`dublin-core/dc.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd|`bc1d454db1bb20dfb1867a3fe0cf007775fc4afa33a5df425c12d854f049f1f6`|
|`dublin-core/dcterms.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd|`6328c8b574c166f8ebc28d07231e6ee47121e9791689b70c3afa665f22099fed`|
|`dublin-core/dcmitype.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dcmitype.xsd|`4980845d0bedcf45e707fa64eb47492ae4f95ac4ae42f5c3c68b58c0bc9e8e49`|
本地适配规范化三份文件的行尾空白与缩进,并修改 `dc.xsd` / `dcterms.xsd` 的 XML 命名空间 import 路径,复用已随包提供的 `ISO-IEC29500-4_2016/xml.xsd`;`dcmitype.xsd` 仅调整空白。Office `opc-coreProperties.xsd` 改为引用本地 `dublin-core/`,不改变命名空间 URI 或类型定义。三套技能分别携带完整闭包,独立安装时不依赖其它技能目录。
离线编译与中文 XML 回归:从市场仓库根运行 `uv run scripts/office/test_offline_resources.py`。运行时仍需要 `lxml` / `defusedxml`;本文件不表示捆绑 LibreOffice 或其它办公系统工具。

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://purl.org/dc/elements/1.1/"
targetNamespace="http://purl.org/dc/elements/1.1/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCMES 1.1 XML Schema
XML Schema for http://purl.org/dc/elements/1.1/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema declares XML elements for the 15 DC elements from the
http://purl.org/dc/elements/1.1/ namespace.
It defines a complexType SimpleLiteral which permits mixed content
and makes the xml:lang attribute available. It disallows child elements by
use of minOcccurs/maxOccurs.
However, this complexType does permit the derivation of other complexTypes
which would permit child elements.
All elements are declared as substitutable for the abstract element any,
which means that the default type for all elements is dc:SimpleLiteral.
</xs:documentation>
</xs:annotation>
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="../ISO-IEC29500-4_2016/xml.xsd">
</xs:import>
<xs:complexType name="SimpleLiteral">
<xs:annotation>
<xs:documentation xml:lang="en">
This is the default type for all of the DC elements.
It permits text content only with optional
xml:lang attribute.
Text is allowed because mixed="true", but sub-elements
are disallowed because minOccurs="0" and maxOccurs="0"
are on the xs:any tag.
This complexType allows for restriction or extension permitting
child elements.
</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="true">
<xs:restriction base="xs:anyType">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="0"/>
</xs:sequence>
<xs:attribute ref="xml:lang" use="optional"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:element name="any" type="SimpleLiteral" abstract="true"/>
<xs:element name="title" substitutionGroup="any"/>
<xs:element name="creator" substitutionGroup="any"/>
<xs:element name="subject" substitutionGroup="any"/>
<xs:element name="description" substitutionGroup="any"/>
<xs:element name="publisher" substitutionGroup="any"/>
<xs:element name="contributor" substitutionGroup="any"/>
<xs:element name="date" substitutionGroup="any"/>
<xs:element name="type" substitutionGroup="any"/>
<xs:element name="format" substitutionGroup="any"/>
<xs:element name="identifier" substitutionGroup="any"/>
<xs:element name="source" substitutionGroup="any"/>
<xs:element name="language" substitutionGroup="any"/>
<xs:element name="relation" substitutionGroup="any"/>
<xs:element name="coverage" substitutionGroup="any"/>
<xs:element name="rights" substitutionGroup="any"/>
<xs:group name="elementsGroup">
<xs:annotation>
<xs:documentation xml:lang="en">
This group is included as a convenience for schema authors
who need to refer to all the elements in the
http://purl.org/dc/elements/1.1/ namespace.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="any"/>
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="elementContainer">
<xs:annotation>
<xs:documentation xml:lang="en">
This complexType is included as a convenience for schema authors who need to define a root
or container element for all of the DC elements.
</xs:documentation>
</xs:annotation>
<xs:choice>
<xs:group ref="elementsGroup"/>
</xs:choice>
</xs:complexType>
</xs:schema>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://purl.org/dc/dcmitype/"
targetNamespace="http://purl.org/dc/dcmitype/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCMI Type Vocabulary XML Schema
XML Schema for http://purl.org/dc/dcmitype/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema defines a simpleType which enumerates
the allowable values for the DCMI Type Vocabulary.
</xs:documentation>
</xs:annotation>
<xs:simpleType name="DCMIType">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:Name">
<xs:enumeration value="Collection"/>
<xs:enumeration value="Dataset"/>
<xs:enumeration value="Event"/>
<xs:enumeration value="Image"/>
<xs:enumeration value="InteractiveResource"/>
<xs:enumeration value="Service"/>
<xs:enumeration value="Software"/>
<xs:enumeration value="Sound"/>
<xs:enumeration value="Text"/>
<xs:enumeration value="PhysicalObject"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:schema>

View File

@@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcmitype="http://purl.org/dc/dcmitype/"
targetNamespace="http://purl.org/dc/terms/"
xmlns="http://purl.org/dc/terms/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCterms XML Schema
XML Schema for http://purl.org/dc/terms/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema declares XML elements for the DC elements and
DC element refinements from the http://purl.org/dc/terms/ namespace.
It reuses the complexType dc:SimpleLiteral, imported from the dc.xsd
schema, which permits simple element content, and makes the xml:lang
attribute available.
This complexType permits the derivation of other complexTypes
which would permit child elements.
DC elements are declared as substitutable for the abstract element dc:any, and
DC element refinements are defined as substitutable for the base elements
which they refine.
This means that the default type for all XML elements (i.e. all DC elements and
element refinements) is dc:SimpleLiteral.
Encoding schemes are defined as complexTypes which are restrictions
of the dc:SimpleLiteral complexType. These complexTypes restrict
values to an appropriates syntax or format using data typing,
regular expressions, or enumerated lists.
In order to specify one of these encodings an xsi:type attribute must
be used in the instance document.
Also, note that one shortcoming of this approach is that any type can be
applied to any of the elements or refinements. There is no convenient way
to restrict types to specific elements using this approach.
</xs:documentation>
</xs:annotation>
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="../ISO-IEC29500-4_2016/xml.xsd">
</xs:import>
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="dc.xsd"/>
<xs:import namespace="http://purl.org/dc/dcmitype/"
schemaLocation="dcmitype.xsd"/>
<xs:element name="alternative" substitutionGroup="dc:title"/>
<xs:element name="tableOfContents" substitutionGroup="dc:description"/>
<xs:element name="abstract" substitutionGroup="dc:description"/>
<xs:element name="created" substitutionGroup="dc:date"/>
<xs:element name="valid" substitutionGroup="dc:date"/>
<xs:element name="available" substitutionGroup="dc:date"/>
<xs:element name="issued" substitutionGroup="dc:date"/>
<xs:element name="modified" substitutionGroup="dc:date"/>
<xs:element name="dateAccepted" substitutionGroup="dc:date"/>
<xs:element name="dateCopyrighted" substitutionGroup="dc:date"/>
<xs:element name="dateSubmitted" substitutionGroup="dc:date"/>
<xs:element name="extent" substitutionGroup="dc:format"/>
<xs:element name="medium" substitutionGroup="dc:format"/>
<xs:element name="isVersionOf" substitutionGroup="dc:relation"/>
<xs:element name="hasVersion" substitutionGroup="dc:relation"/>
<xs:element name="isReplacedBy" substitutionGroup="dc:relation"/>
<xs:element name="replaces" substitutionGroup="dc:relation"/>
<xs:element name="isRequiredBy" substitutionGroup="dc:relation"/>
<xs:element name="requires" substitutionGroup="dc:relation"/>
<xs:element name="isPartOf" substitutionGroup="dc:relation"/>
<xs:element name="hasPart" substitutionGroup="dc:relation"/>
<xs:element name="isReferencedBy" substitutionGroup="dc:relation"/>
<xs:element name="references" substitutionGroup="dc:relation"/>
<xs:element name="isFormatOf" substitutionGroup="dc:relation"/>
<xs:element name="hasFormat" substitutionGroup="dc:relation"/>
<xs:element name="conformsTo" substitutionGroup="dc:relation"/>
<xs:element name="spatial" substitutionGroup="dc:coverage"/>
<xs:element name="temporal" substitutionGroup="dc:coverage"/>
<xs:element name="audience" substitutionGroup="dc:any"/>
<xs:element name="mediator" substitutionGroup="audience"/>
<xs:element name="educationLevel" substitutionGroup="audience"/>
<xs:element name="accessRights" substitutionGroup="dc:rights"/>
<xs:element name="bibliographicCitation" substitutionGroup="dc:identifier"/>
<xs:complexType name="LCSH">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="MESH">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="DDC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="LCC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="UDC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Period">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="W3CDTF">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:union memberTypes="xs:gYear xs:gYearMonth xs:date xs:dateTime"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="DCMIType">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="dcmitype:DCMIType"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="IMT">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="URI">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ISO639-2">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="RFC1766">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:language"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="RFC3066">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:language"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Point">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ISO3166">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Box">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="TGN">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:group name="elementsAndRefinementsGroup">
<xs:annotation>
<xs:documentation xml:lang="en">
This group is included as a convenience for schema authors
who need to refer to all the DC elements and element refinements
in the http://purl.org/dc/elements/1.1/ and
http://purl.org/dc/terms namespaces.
N.B. Refinements available via substitution groups.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="dc:any" />
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="elementOrRefinementContainer">
<xs:annotation>
<xs:documentation xml:lang="en">
This is included as a convenience for schema authors who need to define a root
or container element for all of the DC elements and element refinements.
</xs:documentation>
</xs:annotation>
<xs:choice>
<xs:group ref="elementsAndRefinementsGroup"/>
</xs:choice>
</xs:complexType>
</xs:schema>

View File

@@ -5,9 +5,9 @@
xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" blockDefault="#all">
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
schemaLocation="../../dublin-core/dc.xsd"/>
<xs:import namespace="http://purl.org/dc/terms/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
schemaLocation="../../dublin-core/dcterms.xsd"/>
<xs:import id="xml" namespace="http://www.w3.org/XML/1998/namespace"/>
<xs:element name="coreProperties" type="CT_CoreProperties"/>

View File

@@ -1,4 +1,5 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" targetNamespace="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:st="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" targetNamespace="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:attribute name="storeItemChecksum" type="w12:ST_String"/>
<xsd:attribute name="storeItemChecksum" type="st:ST_String"/>
</xsd:schema>

View File

@@ -1,7 +1,8 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:st="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:complexType name="CT_SymEx">
<xsd:attribute name="font" type="w12:ST_String"/>
<xsd:attribute name="font" type="st:ST_String"/>
<xsd:attribute name="char" type="w12:ST_LongHexNumber"/>
</xsd:complexType>
<xsd:element name="symEx" type="CT_SymEx"/>

View File

@@ -760,7 +760,8 @@ class BaseSchemaValidator:
)
schema = lxml.etree.XMLSchema(xsd_doc)
with open(xml_file, "r") as f:
# 按 XML 自身的编码声明读取,避免 Windows 默认 GBK 破坏 UTF-8 文档。
with open(xml_file, "rb") as f:
xml_doc = lxml.etree.parse(f)
xml_doc, _ = self._remove_template_tags_from_text_nodes(xml_doc)

View File

@@ -13,7 +13,7 @@ description: >-
content afterward. If a .pptx file needs to be opened, created, or touched,
use this skill. Use when 用户提到 PPT、演示文稿、幻灯片、演讲稿、汇报材料、
pptx、创建演示、编辑幻灯片。
version: 1.0.4
version: 1.0.5
type: procedural
risk_level: low
status: enabled
@@ -26,7 +26,7 @@ tags:
- office
metadata:
author: anthropic
updated_at: '2026-05-04'
updated_at: '2026-10-14'
i18n:
default_locale: en-US
source_locale: zh-CN

View File

@@ -30,14 +30,14 @@
},
"release": {
"state": "known",
"version": "1.0.4",
"version": "1.0.5",
"versionScheme": "semver"
},
"timestamps": {
"catalogUpdatedAt": {
"state": "known",
"value": "2026-07-07T13:14:31Z",
"precision": "second"
"value": "2026-10-14",
"precision": "day"
},
"releasePublishedAt": {
"state": "unknown"

View File

@@ -0,0 +1,13 @@
# Office 离线 Schema 依赖
此目录包含 Office 元数据校验所需的 Dublin Core XML Schema。XML schemas Copyright © 2011 [DCMI](https://www.dublincore.org/),按 [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) 使用;许可依据见 [DCMI Schema Use Notice](https://www.dublincore.org/about/copyright/)。上游 Schema 标注创建日期为 2003-04-02,原作者与文档注释保留在文件内。
|本地文件|原始来源|原始文件 SHA-256|
|---|---|---|
|`dublin-core/dc.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd|`bc1d454db1bb20dfb1867a3fe0cf007775fc4afa33a5df425c12d854f049f1f6`|
|`dublin-core/dcterms.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd|`6328c8b574c166f8ebc28d07231e6ee47121e9791689b70c3afa665f22099fed`|
|`dublin-core/dcmitype.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dcmitype.xsd|`4980845d0bedcf45e707fa64eb47492ae4f95ac4ae42f5c3c68b58c0bc9e8e49`|
本地适配规范化三份文件的行尾空白与缩进,并修改 `dc.xsd` / `dcterms.xsd` 的 XML 命名空间 import 路径,复用已随包提供的 `ISO-IEC29500-4_2016/xml.xsd`;`dcmitype.xsd` 仅调整空白。Office `opc-coreProperties.xsd` 改为引用本地 `dublin-core/`,不改变命名空间 URI 或类型定义。三套技能分别携带完整闭包,独立安装时不依赖其它技能目录。
离线编译与中文 XML 回归:从市场仓库根运行 `uv run scripts/office/test_offline_resources.py`。运行时仍需要 `lxml` / `defusedxml`;本文件不表示捆绑 LibreOffice 或其它办公系统工具。

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://purl.org/dc/elements/1.1/"
targetNamespace="http://purl.org/dc/elements/1.1/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCMES 1.1 XML Schema
XML Schema for http://purl.org/dc/elements/1.1/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema declares XML elements for the 15 DC elements from the
http://purl.org/dc/elements/1.1/ namespace.
It defines a complexType SimpleLiteral which permits mixed content
and makes the xml:lang attribute available. It disallows child elements by
use of minOcccurs/maxOccurs.
However, this complexType does permit the derivation of other complexTypes
which would permit child elements.
All elements are declared as substitutable for the abstract element any,
which means that the default type for all elements is dc:SimpleLiteral.
</xs:documentation>
</xs:annotation>
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="../ISO-IEC29500-4_2016/xml.xsd">
</xs:import>
<xs:complexType name="SimpleLiteral">
<xs:annotation>
<xs:documentation xml:lang="en">
This is the default type for all of the DC elements.
It permits text content only with optional
xml:lang attribute.
Text is allowed because mixed="true", but sub-elements
are disallowed because minOccurs="0" and maxOccurs="0"
are on the xs:any tag.
This complexType allows for restriction or extension permitting
child elements.
</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="true">
<xs:restriction base="xs:anyType">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="0"/>
</xs:sequence>
<xs:attribute ref="xml:lang" use="optional"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:element name="any" type="SimpleLiteral" abstract="true"/>
<xs:element name="title" substitutionGroup="any"/>
<xs:element name="creator" substitutionGroup="any"/>
<xs:element name="subject" substitutionGroup="any"/>
<xs:element name="description" substitutionGroup="any"/>
<xs:element name="publisher" substitutionGroup="any"/>
<xs:element name="contributor" substitutionGroup="any"/>
<xs:element name="date" substitutionGroup="any"/>
<xs:element name="type" substitutionGroup="any"/>
<xs:element name="format" substitutionGroup="any"/>
<xs:element name="identifier" substitutionGroup="any"/>
<xs:element name="source" substitutionGroup="any"/>
<xs:element name="language" substitutionGroup="any"/>
<xs:element name="relation" substitutionGroup="any"/>
<xs:element name="coverage" substitutionGroup="any"/>
<xs:element name="rights" substitutionGroup="any"/>
<xs:group name="elementsGroup">
<xs:annotation>
<xs:documentation xml:lang="en">
This group is included as a convenience for schema authors
who need to refer to all the elements in the
http://purl.org/dc/elements/1.1/ namespace.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="any"/>
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="elementContainer">
<xs:annotation>
<xs:documentation xml:lang="en">
This complexType is included as a convenience for schema authors who need to define a root
or container element for all of the DC elements.
</xs:documentation>
</xs:annotation>
<xs:choice>
<xs:group ref="elementsGroup"/>
</xs:choice>
</xs:complexType>
</xs:schema>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://purl.org/dc/dcmitype/"
targetNamespace="http://purl.org/dc/dcmitype/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCMI Type Vocabulary XML Schema
XML Schema for http://purl.org/dc/dcmitype/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema defines a simpleType which enumerates
the allowable values for the DCMI Type Vocabulary.
</xs:documentation>
</xs:annotation>
<xs:simpleType name="DCMIType">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:Name">
<xs:enumeration value="Collection"/>
<xs:enumeration value="Dataset"/>
<xs:enumeration value="Event"/>
<xs:enumeration value="Image"/>
<xs:enumeration value="InteractiveResource"/>
<xs:enumeration value="Service"/>
<xs:enumeration value="Software"/>
<xs:enumeration value="Sound"/>
<xs:enumeration value="Text"/>
<xs:enumeration value="PhysicalObject"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:schema>

View File

@@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcmitype="http://purl.org/dc/dcmitype/"
targetNamespace="http://purl.org/dc/terms/"
xmlns="http://purl.org/dc/terms/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCterms XML Schema
XML Schema for http://purl.org/dc/terms/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema declares XML elements for the DC elements and
DC element refinements from the http://purl.org/dc/terms/ namespace.
It reuses the complexType dc:SimpleLiteral, imported from the dc.xsd
schema, which permits simple element content, and makes the xml:lang
attribute available.
This complexType permits the derivation of other complexTypes
which would permit child elements.
DC elements are declared as substitutable for the abstract element dc:any, and
DC element refinements are defined as substitutable for the base elements
which they refine.
This means that the default type for all XML elements (i.e. all DC elements and
element refinements) is dc:SimpleLiteral.
Encoding schemes are defined as complexTypes which are restrictions
of the dc:SimpleLiteral complexType. These complexTypes restrict
values to an appropriates syntax or format using data typing,
regular expressions, or enumerated lists.
In order to specify one of these encodings an xsi:type attribute must
be used in the instance document.
Also, note that one shortcoming of this approach is that any type can be
applied to any of the elements or refinements. There is no convenient way
to restrict types to specific elements using this approach.
</xs:documentation>
</xs:annotation>
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="../ISO-IEC29500-4_2016/xml.xsd">
</xs:import>
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="dc.xsd"/>
<xs:import namespace="http://purl.org/dc/dcmitype/"
schemaLocation="dcmitype.xsd"/>
<xs:element name="alternative" substitutionGroup="dc:title"/>
<xs:element name="tableOfContents" substitutionGroup="dc:description"/>
<xs:element name="abstract" substitutionGroup="dc:description"/>
<xs:element name="created" substitutionGroup="dc:date"/>
<xs:element name="valid" substitutionGroup="dc:date"/>
<xs:element name="available" substitutionGroup="dc:date"/>
<xs:element name="issued" substitutionGroup="dc:date"/>
<xs:element name="modified" substitutionGroup="dc:date"/>
<xs:element name="dateAccepted" substitutionGroup="dc:date"/>
<xs:element name="dateCopyrighted" substitutionGroup="dc:date"/>
<xs:element name="dateSubmitted" substitutionGroup="dc:date"/>
<xs:element name="extent" substitutionGroup="dc:format"/>
<xs:element name="medium" substitutionGroup="dc:format"/>
<xs:element name="isVersionOf" substitutionGroup="dc:relation"/>
<xs:element name="hasVersion" substitutionGroup="dc:relation"/>
<xs:element name="isReplacedBy" substitutionGroup="dc:relation"/>
<xs:element name="replaces" substitutionGroup="dc:relation"/>
<xs:element name="isRequiredBy" substitutionGroup="dc:relation"/>
<xs:element name="requires" substitutionGroup="dc:relation"/>
<xs:element name="isPartOf" substitutionGroup="dc:relation"/>
<xs:element name="hasPart" substitutionGroup="dc:relation"/>
<xs:element name="isReferencedBy" substitutionGroup="dc:relation"/>
<xs:element name="references" substitutionGroup="dc:relation"/>
<xs:element name="isFormatOf" substitutionGroup="dc:relation"/>
<xs:element name="hasFormat" substitutionGroup="dc:relation"/>
<xs:element name="conformsTo" substitutionGroup="dc:relation"/>
<xs:element name="spatial" substitutionGroup="dc:coverage"/>
<xs:element name="temporal" substitutionGroup="dc:coverage"/>
<xs:element name="audience" substitutionGroup="dc:any"/>
<xs:element name="mediator" substitutionGroup="audience"/>
<xs:element name="educationLevel" substitutionGroup="audience"/>
<xs:element name="accessRights" substitutionGroup="dc:rights"/>
<xs:element name="bibliographicCitation" substitutionGroup="dc:identifier"/>
<xs:complexType name="LCSH">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="MESH">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="DDC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="LCC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="UDC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Period">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="W3CDTF">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:union memberTypes="xs:gYear xs:gYearMonth xs:date xs:dateTime"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="DCMIType">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="dcmitype:DCMIType"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="IMT">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="URI">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ISO639-2">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="RFC1766">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:language"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="RFC3066">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:language"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Point">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ISO3166">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Box">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="TGN">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:group name="elementsAndRefinementsGroup">
<xs:annotation>
<xs:documentation xml:lang="en">
This group is included as a convenience for schema authors
who need to refer to all the DC elements and element refinements
in the http://purl.org/dc/elements/1.1/ and
http://purl.org/dc/terms namespaces.
N.B. Refinements available via substitution groups.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="dc:any" />
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="elementOrRefinementContainer">
<xs:annotation>
<xs:documentation xml:lang="en">
This is included as a convenience for schema authors who need to define a root
or container element for all of the DC elements and element refinements.
</xs:documentation>
</xs:annotation>
<xs:choice>
<xs:group ref="elementsAndRefinementsGroup"/>
</xs:choice>
</xs:complexType>
</xs:schema>

View File

@@ -5,9 +5,9 @@
xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" blockDefault="#all">
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
schemaLocation="../../dublin-core/dc.xsd"/>
<xs:import namespace="http://purl.org/dc/terms/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
schemaLocation="../../dublin-core/dcterms.xsd"/>
<xs:import id="xml" namespace="http://www.w3.org/XML/1998/namespace"/>
<xs:element name="coreProperties" type="CT_CoreProperties"/>

View File

@@ -1,4 +1,5 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" targetNamespace="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:st="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" targetNamespace="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:attribute name="storeItemChecksum" type="w12:ST_String"/>
<xsd:attribute name="storeItemChecksum" type="st:ST_String"/>
</xsd:schema>

View File

@@ -1,7 +1,8 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:st="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:complexType name="CT_SymEx">
<xsd:attribute name="font" type="w12:ST_String"/>
<xsd:attribute name="font" type="st:ST_String"/>
<xsd:attribute name="char" type="w12:ST_LongHexNumber"/>
</xsd:complexType>
<xsd:element name="symEx" type="CT_SymEx"/>

View File

@@ -760,7 +760,8 @@ class BaseSchemaValidator:
)
schema = lxml.etree.XMLSchema(xsd_doc)
with open(xml_file, "r") as f:
# 按 XML 自身的编码声明读取,避免 Windows 默认 GBK 破坏 UTF-8 文档。
with open(xml_file, "rb") as f:
xml_doc = lxml.etree.parse(f)
xml_doc, _ = self._remove_template_tags_from_text_nodes(xml_doc)

View File

@@ -1,7 +1,7 @@
---
name: presentation-forge
description: "创建中文商业汇报,从主题、文档或 slides.md 生成原生可编辑 PPTX,提供 Markdown-first 实时画布、样式切换和同版导出,使用 image-2 辅助生成独立视觉资产,把截图或图片型幻灯片重建为可编辑 PPTX/SVG,或用原生 PPTX 模板填充新内容。用户要求制作售前方案、项目汇报、产品介绍、行业分析、培训材料、像 Markdown 一样编辑并导出、AIPPT 式可编辑演示、套用 PowerPoint 模板、图片页转可编辑 PowerPoint、重建幻灯片或输出 SVG 时使用。"
version: 0.1.0
version: 0.1.1
type: procedural
risk_level: low
status: enabled
@@ -13,7 +13,7 @@ tags:
- slides
metadata:
author: Ronnie2025
updated_at: '2026-08-10'
updated_at: '2026-10-14'
i18n:
default_locale: en-US
source_locale: zh-CN

View File

@@ -1,6 +1,6 @@
name: presentation-forge
description: "创建中文商业汇报,从主题、文档或 slides.md 生成原生可编辑 PPTX,提供 Markdown-first 实时画布、样式切换和同版导出,使用 image-2 辅助生成独立视觉资产,把截图或图片型幻灯片重建为可编辑 PPTX/SVG,或用原生 PPTX 模板填充新内容。用户要求制作售前方案、项目汇报、产品介绍、行业分析、培训材料、像 Markdown 一样编辑并导出、AIPPT 式可编辑演示、套用 PowerPoint 模板、图片页转可编辑 PowerPoint、重建幻灯片或输出 SVG 时使用。"
version: 0.1.0
version: 0.1.1
type: procedural
risk_level: low
status: enabled
@@ -12,7 +12,7 @@ tags:
- slides
metadata:
author: Ronnie2025
updated_at: '2026-08-10'
updated_at: '2026-10-14'
i18n:
default_locale: en-US
source_locale: zh-CN

View File

@@ -0,0 +1,119 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import html
import json
from pathlib import Path
def esc(value: object) -> str:
return html.escape(str(value or ""))
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--manifest", required=True)
parser.add_argument("--out", required=True)
args = parser.parse_args()
manifest = json.loads(Path(args.manifest).read_text(encoding="utf-8"))
slides = manifest["slides"]
manifest_json = json.dumps(manifest, ensure_ascii=False).replace("</", "<\\/")
document = f'''<!doctype html>
<meta charset="utf-8">
<title>{esc(manifest.get('session_id'))} · Presentation Forge Canvas</title>
<style>
:root{{--panel:#191e2a;--line:#354052;--ink:#f3f6ff;--muted:#9da8bd;--accent:#4f7cff;--thumb-width:160px;--inspector-width:320px}}
*{{box-sizing:border-box}} body{{margin:0;background:#0f131d;color:var(--ink);font:14px Inter,"PingFang SC",sans-serif}}
button{{font:inherit;color:inherit}} .app{{height:100vh;display:grid;grid-template-rows:52px 1fr}}
header{{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:0 16px;background:var(--panel);border-bottom:1px solid var(--line)}}
.header-actions{{display:flex;align-items:center;gap:8px}} .toolbar{{border:1px solid var(--line);background:#111520;padding:7px 10px;cursor:pointer}}
.status{{color:var(--muted)}} .export{{border:0;background:#315efb;padding:8px 14px;cursor:pointer}}
.main{{display:grid;grid-template-columns:var(--thumb-width) minmax(0,1fr) var(--inspector-width);min-height:0;transition:grid-template-columns .18s ease}}
body.thumbs-collapsed .main{{grid-template-columns:0 minmax(0,1fr) var(--inspector-width)}}
body.inspector-collapsed .main{{grid-template-columns:var(--thumb-width) minmax(0,1fr) 0}}
body.thumbs-collapsed.inspector-collapsed .main,body.focus-canvas .main{{grid-template-columns:0 minmax(0,1fr) 0}}
body.thumbs-collapsed .thumbs,body.focus-canvas .thumbs{{display:none}}
body.inspector-collapsed aside.props,body.focus-canvas aside.props{{display:none}}
.thumbs{{overflow:auto;padding:12px;background:#151a25;border-right:1px solid var(--line)}}
.thumb{{display:block;width:100%;margin:0 0 10px;padding:8px;text-align:left;background:#222938;border:1px solid #3a4353;cursor:pointer}}
.thumb.active{{outline:2px solid #6e8dff}} .thumb-title{{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}} .thumb-meta{{color:var(--muted);font-size:11px}}
.stage-wrap{{display:flex;align-items:center;justify-content:center;overflow:auto;padding:16px;background:#111520}}
.stage{{position:relative;width:min(100%,calc((100vh - 84px)*16/9));min-width:746px;min-height:420px;aspect-ratio:16/9;background:#0a0f1e;overflow:hidden;box-shadow:0 18px 60px #0008}}
.element{{position:absolute;transform-origin:center;white-space:pre-wrap;overflow:hidden}}
.element[data-type=text]{{display:flex;padding:2px}}
.element[data-editable=true]{{cursor:text}} .element.selected{{outline:2px solid #ffd056;outline-offset:2px}}
.shape{{border-style:solid}} .connector{{height:0!important;transform-origin:left center;border-top-style:solid}}
aside.props{{padding:14px;background:var(--panel);border-left:1px solid var(--line);overflow:auto}}
.field{{margin:0 0 14px}} label{{display:block;color:var(--muted);margin-bottom:5px}} input{{width:100%;background:#111520;color:var(--ink);border:1px solid var(--line);padding:7px}}
.empty{{color:var(--muted)}} .count{{color:#25d0d8}}
@media(max-width:1100px){{:root{{--thumb-width:128px;--inspector-width:300px}}}}
</style>
<body class="inspector-collapsed">
<div class="app">
<header><div><strong>{esc(manifest.get('session_id'))}</strong> <span class="status" id="status">画布编辑中 · <span class="count">{len(slides)} 页</span></span></div><div class="header-actions"><button class="toolbar" id="toggle-thumbs">页面列表</button><button class="toolbar" id="toggle-inspector">对象编辑</button><button class="toolbar" id="focus-canvas">专注画布</button><button class="export" id="export">导出 PPTX</button></div></header>
<div class="main">
<nav class="thumbs" id="thumbs"></nav>
<main class="stage-wrap"><section class="stage" id="stage"></section></main>
<aside class="props"><section id="object-panel"><h3 id="page-title">页面</h3><div id="props" class="empty">请选择文字对象进行编辑。</div></section></aside>
</div>
</div>
<script type="application/json" id="manifest">{manifest_json}</script>
<script>
(() => {{
const manifest = JSON.parse(document.querySelector('#manifest').textContent);
if (manifest.slide_count !== manifest.slides.length) throw new Error('slide_count 与 slides 长度不一致');
const state = structuredClone(manifest.slides);
const thumbs = document.querySelector('#thumbs'), stage = document.querySelector('#stage'), props = document.querySelector('#props');
let active = 0, selected = null, sourceMarkdown = manifest.authoring?.markdown || '';
const pct = (v,total) => `${{v/total*100}}%`;
const renderThumbs = () => {{
thumbs.innerHTML = '';
state.forEach((slide,index) => {{
const b=document.createElement('button'); b.className='thumb'+(index===active?' active':''); b.type='button';
b.innerHTML=`<span class="thumb-title">${{slide.slide_number}}. ${{slide.title}}</span><span class="thumb-meta">${{slide.archetype||'slide'}} · ${{slide.elements.length}} 个对象</span>`;
b.onclick=()=>{{active=index; selected=null; render();}}; thumbs.appendChild(b);
}});
}};
const renderProps = () => {{
document.querySelector('#page-title').textContent=`第 ${{state[active].slide_number}} 页 · ${{state[active].title}}`;
if(!selected || selected.type!=='text'){{props.className='empty'; props.textContent='请选择文字对象进行编辑。'; return;}}
props.className=''; props.innerHTML=`<div class="field"><label>对象</label><input value="${{selected.id}}" disabled></div><div class="field"><label>文字</label><input id="text-value"></div><div class="field"><label>字号(pt)</label><input id="font-size" type="number" step="0.5"></div><div class="field"><label>颜色</label><input id="font-color" type="color"></div>`;
document.querySelector('#text-value').value=selected.text||''; document.querySelector('#font-size').value=selected.style?.font_size_pt||18; document.querySelector('#font-color').value='#'+(selected.style?.font_color||'F7F9FF');
document.querySelector('#text-value').oninput=e=>{{selected.text=e.target.value; renderStage();}};
document.querySelector('#font-size').oninput=e=>{{selected.style.font_size_pt=Number(e.target.value); renderStage();}};
document.querySelector('#font-color').oninput=e=>{{selected.style.font_color=e.target.value.slice(1).toUpperCase(); renderStage();}};
}};
const renderStage = () => {{
const slide=state[active], c=slide.canvas||{{width:1920,height:1080}}; stage.innerHTML='';
const preset=manifest.style_catalog.find(x=>x.style_id===slide.style.style_id&&x.variant_id===slide.style.variant_id)||manifest.style_catalog[0];
const bg=Array.isArray(preset.design_tokens.background)?preset.design_tokens.background[0]:preset.design_tokens.background; stage.style.background=bg;
[...slide.elements].sort((a,b)=>(a.z_index||0)-(b.z_index||0)).forEach(el=>{{
const node=document.createElement('div'); node.dataset.type=el.type; node.dataset.editable=String(el.editable!==false); node.className='element '+(el.type==='shape'?'shape':el.type==='connector'?'connector':'')+(selected===el?' selected':'');
const [x,y,w,h]=el.bbox; Object.assign(node.style,{{left:pct(x,c.width),top:pct(y,c.height),width:pct(w,c.width),height:pct(h,c.height),zIndex:el.z_index||0,transform:`rotate(${{el.rotation||0}}deg)`}});
const s=el.style||{{}}; if(s.fill)node.style.background='#'+s.fill; if(s.line)node.style.borderColor='#'+s.line; node.style.borderWidth=(s.line_width_pt||0)+'px';
if(el.type==='shape'){{node.style.borderRadius=['ellipse','oval'].includes(el.geometry)?'50%':el.geometry==='rounded_rectangle'?'12px':'0';}}
if(el.type==='connector'){{const length=Math.hypot(w,h);node.style.width=pct(length,c.width);node.style.height='0';node.style.transform=`rotate(${{Math.atan2(h,w)*180/Math.PI+(el.rotation||0)}}deg)`;}}
if(el.type==='text'){{node.textContent=el.text||''; node.contentEditable=el.editable!==false; node.style.fontSize=`${{(s.font_size_pt||18)*4/3*stage.clientWidth/c.width}}px`; node.style.color='#'+(s.font_color||'F7F9FF'); node.style.fontWeight=s.bold?'700':'400'; node.style.textAlign=s.align||'left'; node.style.alignItems=s.vertical_align==='top'?'flex-start':s.vertical_align==='bottom'?'flex-end':'center'; node.oninput=()=>{{el.text=node.textContent;}};}}
node.onclick=e=>{{e.stopPropagation();selected=el;if(el.type==='text')document.body.classList.remove('inspector-collapsed','focus-canvas');renderProps();stage.querySelectorAll('.selected').forEach(n=>n.classList.remove('selected'));node.classList.add('selected');}}; stage.appendChild(node);
}});
}};
const render=()=>{{renderThumbs();renderStage();renderProps();}}; stage.onclick=()=>{{selected=null;renderProps();}};
document.querySelector('#toggle-thumbs').onclick=()=>{{document.body.classList.remove('focus-canvas');document.body.classList.toggle('thumbs-collapsed');}};
document.querySelector('#toggle-inspector').onclick=()=>{{document.body.classList.remove('focus-canvas');document.body.classList.toggle('inspector-collapsed');}};
document.querySelector('#focus-canvas').onclick=()=>document.body.classList.toggle('focus-canvas');
document.querySelector('#export').onclick=async()=>{{
const payload={{schema_version:1,session_id:manifest.session_id,base_revision:manifest.base_revision,document_sha256:manifest.document_sha256,canvas_sha256:manifest.canvas_sha256,slide_count:state.length,slides_markdown:sourceMarkdown,slides:state.map(s=>({{slide_number:s.slide_number,title:s.title,archetype:s.archetype,style:s.style,canvas:s.canvas,elements:s.elements}}))}};
if(!window.openai||typeof window.openai.sendFollowUpMessage!=='function'){{document.querySelector('#status').textContent='当前环境不能提交导出';return;}}
await window.openai.sendFollowUpMessage({{title:'导出画布同版 PPTX',prompt:`使用 presentation-forge 导出以下完整 Markdown + canvas-first 状态。先把 slides_markdown 写回 session/slides.md 并编译;再应用全部 ${{payload.slide_count}} 页 scene 的对象、坐标、样式和层级。若 Markdown 内容与画布对象文字冲突,以当前画布对象为准并回写 Markdown。PPTX 必须与画布同页数、同对象、同文字、同坐标、同样式;禁止另起布局或只提交封面。画布状态:${{JSON.stringify(payload)}}`}});
document.querySelector('#status').textContent=`已提交 ${{payload.slide_count}} 页完整画布状态`;
}};
render();
}})();
</script>'''
Path(args.out).write_text(document, encoding="utf-8")
print(json.dumps({"status": "PASS", "slide_count": len(slides), "out": str(Path(args.out).resolve())}, ensure_ascii=False))
if __name__ == "__main__":
main()

View File

@@ -30,14 +30,14 @@
},
"release": {
"state": "known",
"version": "0.1.0",
"version": "0.1.1",
"versionScheme": "semver"
},
"timestamps": {
"catalogUpdatedAt": {
"state": "known",
"value": "2026-08-23T15:31:26Z",
"precision": "second"
"value": "2026-10-14",
"precision": "day"
},
"releasePublishedAt": {
"state": "unknown"

View File

@@ -29,7 +29,7 @@ canvas-first 不是示意界面。画布和最终 PPTX 必须使用同一份完
```bash
python scripts/editor_bridge.py export --session <session>
cp assets/editor/render_editor_canvas.py <session>/analysis/render_editor_canvas.py
cp scripts/render_editor_canvas.py <session>/analysis/render_editor_canvas.py
python scripts/render_editor_canvas.py \
--manifest <session>/reports/editor-manifest.json \
--out <session>/reports/editor-canvas.html

View File

@@ -16,7 +16,7 @@ description: >-
report, standalone Python script, database pipeline, or Google Sheets API
integration, even if tabular data is involved. Use when 用户提到 Excel、
电子表格、xlsx、表格处理、公式计算、数据清洗、图表、CSV导入导出。
version: 1.0.3
version: 1.0.4
type: procedural
risk_level: low
status: enabled
@@ -28,7 +28,7 @@ tags:
- office
metadata:
author: anthropic
updated_at: '2026-04-13'
updated_at: '2026-10-14'
i18n:
default_locale: en-US
source_locale: zh-CN

View File

@@ -29,14 +29,14 @@
},
"release": {
"state": "known",
"version": "1.0.3",
"version": "1.0.4",
"versionScheme": "semver"
},
"timestamps": {
"catalogUpdatedAt": {
"state": "known",
"value": "2026-07-07T13:14:31Z",
"precision": "second"
"value": "2026-10-14",
"precision": "day"
},
"releasePublishedAt": {
"state": "unknown"

View File

@@ -0,0 +1,13 @@
# Office 离线 Schema 依赖
此目录包含 Office 元数据校验所需的 Dublin Core XML Schema。XML schemas Copyright © 2011 [DCMI](https://www.dublincore.org/),按 [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) 使用;许可依据见 [DCMI Schema Use Notice](https://www.dublincore.org/about/copyright/)。上游 Schema 标注创建日期为 2003-04-02,原作者与文档注释保留在文件内。
|本地文件|原始来源|原始文件 SHA-256|
|---|---|---|
|`dublin-core/dc.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd|`bc1d454db1bb20dfb1867a3fe0cf007775fc4afa33a5df425c12d854f049f1f6`|
|`dublin-core/dcterms.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd|`6328c8b574c166f8ebc28d07231e6ee47121e9791689b70c3afa665f22099fed`|
|`dublin-core/dcmitype.xsd`|https://www.dublincore.org/schemas/xmls/qdc/2003/04/02/dcmitype.xsd|`4980845d0bedcf45e707fa64eb47492ae4f95ac4ae42f5c3c68b58c0bc9e8e49`|
本地适配规范化三份文件的行尾空白与缩进,并修改 `dc.xsd` / `dcterms.xsd` 的 XML 命名空间 import 路径,复用已随包提供的 `ISO-IEC29500-4_2016/xml.xsd`;`dcmitype.xsd` 仅调整空白。Office `opc-coreProperties.xsd` 改为引用本地 `dublin-core/`,不改变命名空间 URI 或类型定义。三套技能分别携带完整闭包,独立安装时不依赖其它技能目录。
离线编译与中文 XML 回归:从市场仓库根运行 `uv run scripts/office/test_offline_resources.py`。运行时仍需要 `lxml` / `defusedxml`;本文件不表示捆绑 LibreOffice 或其它办公系统工具。

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://purl.org/dc/elements/1.1/"
targetNamespace="http://purl.org/dc/elements/1.1/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCMES 1.1 XML Schema
XML Schema for http://purl.org/dc/elements/1.1/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema declares XML elements for the 15 DC elements from the
http://purl.org/dc/elements/1.1/ namespace.
It defines a complexType SimpleLiteral which permits mixed content
and makes the xml:lang attribute available. It disallows child elements by
use of minOcccurs/maxOccurs.
However, this complexType does permit the derivation of other complexTypes
which would permit child elements.
All elements are declared as substitutable for the abstract element any,
which means that the default type for all elements is dc:SimpleLiteral.
</xs:documentation>
</xs:annotation>
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="../ISO-IEC29500-4_2016/xml.xsd">
</xs:import>
<xs:complexType name="SimpleLiteral">
<xs:annotation>
<xs:documentation xml:lang="en">
This is the default type for all of the DC elements.
It permits text content only with optional
xml:lang attribute.
Text is allowed because mixed="true", but sub-elements
are disallowed because minOccurs="0" and maxOccurs="0"
are on the xs:any tag.
This complexType allows for restriction or extension permitting
child elements.
</xs:documentation>
</xs:annotation>
<xs:complexContent mixed="true">
<xs:restriction base="xs:anyType">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="0"/>
</xs:sequence>
<xs:attribute ref="xml:lang" use="optional"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:element name="any" type="SimpleLiteral" abstract="true"/>
<xs:element name="title" substitutionGroup="any"/>
<xs:element name="creator" substitutionGroup="any"/>
<xs:element name="subject" substitutionGroup="any"/>
<xs:element name="description" substitutionGroup="any"/>
<xs:element name="publisher" substitutionGroup="any"/>
<xs:element name="contributor" substitutionGroup="any"/>
<xs:element name="date" substitutionGroup="any"/>
<xs:element name="type" substitutionGroup="any"/>
<xs:element name="format" substitutionGroup="any"/>
<xs:element name="identifier" substitutionGroup="any"/>
<xs:element name="source" substitutionGroup="any"/>
<xs:element name="language" substitutionGroup="any"/>
<xs:element name="relation" substitutionGroup="any"/>
<xs:element name="coverage" substitutionGroup="any"/>
<xs:element name="rights" substitutionGroup="any"/>
<xs:group name="elementsGroup">
<xs:annotation>
<xs:documentation xml:lang="en">
This group is included as a convenience for schema authors
who need to refer to all the elements in the
http://purl.org/dc/elements/1.1/ namespace.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="any"/>
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="elementContainer">
<xs:annotation>
<xs:documentation xml:lang="en">
This complexType is included as a convenience for schema authors who need to define a root
or container element for all of the DC elements.
</xs:documentation>
</xs:annotation>
<xs:choice>
<xs:group ref="elementsGroup"/>
</xs:choice>
</xs:complexType>
</xs:schema>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://purl.org/dc/dcmitype/"
targetNamespace="http://purl.org/dc/dcmitype/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCMI Type Vocabulary XML Schema
XML Schema for http://purl.org/dc/dcmitype/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema defines a simpleType which enumerates
the allowable values for the DCMI Type Vocabulary.
</xs:documentation>
</xs:annotation>
<xs:simpleType name="DCMIType">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:Name">
<xs:enumeration value="Collection"/>
<xs:enumeration value="Dataset"/>
<xs:enumeration value="Event"/>
<xs:enumeration value="Image"/>
<xs:enumeration value="InteractiveResource"/>
<xs:enumeration value="Service"/>
<xs:enumeration value="Software"/>
<xs:enumeration value="Sound"/>
<xs:enumeration value="Text"/>
<xs:enumeration value="PhysicalObject"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:schema>

View File

@@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcmitype="http://purl.org/dc/dcmitype/"
targetNamespace="http://purl.org/dc/terms/"
xmlns="http://purl.org/dc/terms/"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:annotation>
<xs:documentation xml:lang="en">
DCterms XML Schema
XML Schema for http://purl.org/dc/terms/ namespace
Created 2003-04-02
Created by
Tim Cole (t-cole3@uiuc.edu)
Tom Habing (thabing@uiuc.edu)
Jane Hunter (jane@dstc.edu.au)
Pete Johnston (p.johnston@ukoln.ac.uk),
Carl Lagoze (lagoze@cs.cornell.edu)
This schema declares XML elements for the DC elements and
DC element refinements from the http://purl.org/dc/terms/ namespace.
It reuses the complexType dc:SimpleLiteral, imported from the dc.xsd
schema, which permits simple element content, and makes the xml:lang
attribute available.
This complexType permits the derivation of other complexTypes
which would permit child elements.
DC elements are declared as substitutable for the abstract element dc:any, and
DC element refinements are defined as substitutable for the base elements
which they refine.
This means that the default type for all XML elements (i.e. all DC elements and
element refinements) is dc:SimpleLiteral.
Encoding schemes are defined as complexTypes which are restrictions
of the dc:SimpleLiteral complexType. These complexTypes restrict
values to an appropriates syntax or format using data typing,
regular expressions, or enumerated lists.
In order to specify one of these encodings an xsi:type attribute must
be used in the instance document.
Also, note that one shortcoming of this approach is that any type can be
applied to any of the elements or refinements. There is no convenient way
to restrict types to specific elements using this approach.
</xs:documentation>
</xs:annotation>
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="../ISO-IEC29500-4_2016/xml.xsd">
</xs:import>
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="dc.xsd"/>
<xs:import namespace="http://purl.org/dc/dcmitype/"
schemaLocation="dcmitype.xsd"/>
<xs:element name="alternative" substitutionGroup="dc:title"/>
<xs:element name="tableOfContents" substitutionGroup="dc:description"/>
<xs:element name="abstract" substitutionGroup="dc:description"/>
<xs:element name="created" substitutionGroup="dc:date"/>
<xs:element name="valid" substitutionGroup="dc:date"/>
<xs:element name="available" substitutionGroup="dc:date"/>
<xs:element name="issued" substitutionGroup="dc:date"/>
<xs:element name="modified" substitutionGroup="dc:date"/>
<xs:element name="dateAccepted" substitutionGroup="dc:date"/>
<xs:element name="dateCopyrighted" substitutionGroup="dc:date"/>
<xs:element name="dateSubmitted" substitutionGroup="dc:date"/>
<xs:element name="extent" substitutionGroup="dc:format"/>
<xs:element name="medium" substitutionGroup="dc:format"/>
<xs:element name="isVersionOf" substitutionGroup="dc:relation"/>
<xs:element name="hasVersion" substitutionGroup="dc:relation"/>
<xs:element name="isReplacedBy" substitutionGroup="dc:relation"/>
<xs:element name="replaces" substitutionGroup="dc:relation"/>
<xs:element name="isRequiredBy" substitutionGroup="dc:relation"/>
<xs:element name="requires" substitutionGroup="dc:relation"/>
<xs:element name="isPartOf" substitutionGroup="dc:relation"/>
<xs:element name="hasPart" substitutionGroup="dc:relation"/>
<xs:element name="isReferencedBy" substitutionGroup="dc:relation"/>
<xs:element name="references" substitutionGroup="dc:relation"/>
<xs:element name="isFormatOf" substitutionGroup="dc:relation"/>
<xs:element name="hasFormat" substitutionGroup="dc:relation"/>
<xs:element name="conformsTo" substitutionGroup="dc:relation"/>
<xs:element name="spatial" substitutionGroup="dc:coverage"/>
<xs:element name="temporal" substitutionGroup="dc:coverage"/>
<xs:element name="audience" substitutionGroup="dc:any"/>
<xs:element name="mediator" substitutionGroup="audience"/>
<xs:element name="educationLevel" substitutionGroup="audience"/>
<xs:element name="accessRights" substitutionGroup="dc:rights"/>
<xs:element name="bibliographicCitation" substitutionGroup="dc:identifier"/>
<xs:complexType name="LCSH">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="MESH">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="DDC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="LCC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="UDC">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Period">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="W3CDTF">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:union memberTypes="xs:gYear xs:gYearMonth xs:date xs:dateTime"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="DCMIType">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="dcmitype:DCMIType"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="IMT">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="URI">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ISO639-2">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="RFC1766">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:language"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="RFC3066">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:language"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Point">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ISO3166">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="Box">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="TGN">
<xs:simpleContent>
<xs:restriction base="dc:SimpleLiteral">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:attribute ref="xml:lang" use="prohibited"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:group name="elementsAndRefinementsGroup">
<xs:annotation>
<xs:documentation xml:lang="en">
This group is included as a convenience for schema authors
who need to refer to all the DC elements and element refinements
in the http://purl.org/dc/elements/1.1/ and
http://purl.org/dc/terms namespaces.
N.B. Refinements available via substitution groups.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="dc:any" />
</xs:choice>
</xs:sequence>
</xs:group>
<xs:complexType name="elementOrRefinementContainer">
<xs:annotation>
<xs:documentation xml:lang="en">
This is included as a convenience for schema authors who need to define a root
or container element for all of the DC elements and element refinements.
</xs:documentation>
</xs:annotation>
<xs:choice>
<xs:group ref="elementsAndRefinementsGroup"/>
</xs:choice>
</xs:complexType>
</xs:schema>

View File

@@ -5,9 +5,9 @@
xmlns:dcterms="http://purl.org/dc/terms/" elementFormDefault="qualified" blockDefault="#all">
<xs:import namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
schemaLocation="../../dublin-core/dc.xsd"/>
<xs:import namespace="http://purl.org/dc/terms/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
schemaLocation="../../dublin-core/dcterms.xsd"/>
<xs:import id="xml" namespace="http://www.w3.org/XML/1998/namespace"/>
<xs:element name="coreProperties" type="CT_CoreProperties"/>

View File

@@ -1,4 +1,5 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" targetNamespace="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:st="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" targetNamespace="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:attribute name="storeItemChecksum" type="w12:ST_String"/>
<xsd:attribute name="storeItemChecksum" type="st:ST_String"/>
</xsd:schema>

View File

@@ -1,7 +1,8 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:st="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" schemaLocation="../ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd"/>
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:complexType name="CT_SymEx">
<xsd:attribute name="font" type="w12:ST_String"/>
<xsd:attribute name="font" type="st:ST_String"/>
<xsd:attribute name="char" type="w12:ST_LongHexNumber"/>
</xsd:complexType>
<xsd:element name="symEx" type="CT_SymEx"/>

View File

@@ -760,7 +760,8 @@ class BaseSchemaValidator:
)
schema = lxml.etree.XMLSchema(xsd_doc)
with open(xml_file, "r") as f:
# 按 XML 自身的编码声明读取,避免 Windows 默认 GBK 破坏 UTF-8 文档。
with open(xml_file, "rb") as f:
xml_doc = lxml.etree.parse(f)
xml_doc, _ = self._remove_template_tags_from_text_nodes(xml_doc)