1

我正在开发一个 XML 验证服务,该服务使用多个 XML 模式文件来验证我的应用程序中的 XML 文件。XML Schema 文件大量使用导入。出于这个原因,我需要一个服务,它将命名空间与它们的模式定义(文件位置)相关联。

每个 XML 命名空间都在单独的 XSD 中定义。

我知道我可以使用schemaLocation属性将模式与其文件连接起来,但这需要使用大量相对路径,并且不适用于任意项目结构:

<-- schema.xsd -->
<xsd:import namespace="urn.my.namespace" schemaLocation="..."/>

<-- actual.xml -->
<root xmlns="urn.my.namespace"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn.my.namespace schema.xsd">
</root>

我想创建一个服务,它遍历捆绑包,发现 xsd 文件并将它们的名称空间 - 文件位置关联注册到某种可用于其他 XML 服务的注册表中。

我的 Symfony 项目具有以下结构:

AbcBundle/
    Resources/config/services.xml
    Resources/xsd/
        schema.xsd
        ns1.xsd
        ns2.xsd
        ...
    AbcBundle.php
XyzBundle/
    [same structre]

计划使用:

$nsLocator = $container->get('xml.ns_locator');
$nsLocator->getNamespaceMap();
/* returns array(
    'urn:my:ns1' => '/realpath/to/ns1.xsd',
    'urn:my:ns2' => '/otherpath/to/ns2.xsd',
*/

$nsLocator应该从 Bundle/Resources/xsd/ 目录中自动构建该映射。我喜欢 Symfony 使用其堆栈注册 Bundle/Command 或 Bundle/Controller 的方式。

我正在考虑某种事件侦听器,它会挂接到内核中,一旦注册了所有 Bundle,它就会扫描所有 XSD 并创建一个映射。如果这样做,它将需要缓存,因此它不会在每次执行新请求或命令时重新扫描所有文件。

如何构建该组件并将其连接到内核中?该组件的正确连接点在哪里?它通常是一个好方法吗?

4

1 回答 1

2

您应该能够创建一个编译器通道,该通道将在构建容器时运行(在主通道之后)。

在传递过程中,获取捆绑包列表并遍历它们以创建 xsd 文件列表。最后,将列表传递给您的服务。

要获取捆绑包列表:

$container->getParameter('kernel.bundles')

阅读更多:

于 2012-11-07T12:47:20.900 回答