从 XML Schema 中移除命名空间支持
Posted
技术标签:
【中文标题】从 XML Schema 中移除命名空间支持【英文标题】:Removing namespace support from XML Schema 【发布时间】:2021-11-09 05:54:07 【问题描述】:我正在开发一个基于以前作者工作的框架,并希望将 XML 降级为不支持 XML 命名空间,主要是因为它不需要并且使最终结果过于复杂。
这里是 XML 示例:
<ae:configurations xmlns:ae="http://domain.tld/xml/config/global/envelope" xmlns="http://domain.tld/xml/config/parts/routing">
<ae:configuration context="web">
<routes>
<!-- The last route in case the input URL is just "/". -->
<route name="examples" pattern="^/examples" module="Examples" action="Default">
<route name=".caching" pattern="/caching$" module="Examples" action="Caching" />
<route name=".configuration" pattern="/configuration$" module="Examples" action="Configuration" />
<route name=".exceptions" pattern="/exceptions$" module="Examples" action="Exceptions" />
<route name=".routing" pattern="/routing$" module="Examples" action="Routing" />
<route name=".sessions" pattern="/sessions$" module="Examples" action="Sessions" />
<route name=".database" pattern="/database$" module="Examples" action="Database" />
<route name=".forms" pattern="/forms$" module="Examples" action="Forms" />
<route name=".generator" pattern="/generator$" module="Examples" action="Generator" />
<route name=".templating" pattern="/templating$" module="Examples" action="Templating" />
<route name=".translation" pattern="/translation$" module="Examples" action="Translation" />
</route>
<route name="index" pattern="^/$" module="%chains.default_module%" action="%chains.default_action%" />
</routes>
</ae:configuration>
</ae:configurations>
其中有以下 XSD 文件:
routing.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:types="http://domain.tld/xml/config/global/types"
xmlns:routing="http://domain.tld/xml/config/parts/routing"
targetNamespace="http://domain.tld/xml/config/global/envelope"
elementFormDefault="qualified"
version="$Id$">
<xs:import namespace="http://domain.tld/xml/config/global/types"
schemaLocation="_types.xsd" />
<xs:import namespace="http://domain.tld/xml/config/parts/routing"
schemaLocation="parts/routing.xsd" />
<xs:redefine schemaLocation="_envelope.xsd">
<xs:complexType name="configuration">
<xs:complexContent>
<xs:extension base="configuration">
<xs:group ref="routing:configuration" />
<xs:attributeGroup ref="types:contexts" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
</xs:schema>
parts/routing.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:envelope="http://domain.tld/xml/config/global/envelope"
xmlns:types="http://domain.tld/xml/config/global/types"
xmlns="http://domain.tld/xml/config/parts/routing"
targetNamespace="http://domain.tld/xml/config/parts/routing"
elementFormDefault="qualified"
version="$Id$">
<xs:import namespace="http://domain.tld/xml/config/global/types"
schemaLocation="../_types.xsd" />
<xs:import namespace="http://domain.tld/xml/config/global/envelope"
schemaLocation="../_envelope.xsd" />
<xs:simpleType name="route_name">
<xs:restriction base="xs:string">
<xs:pattern value="[^\+\-]+" />
</xs:restriction>
</xs:simpleType>
<xs:group name="ignores">
<xs:choice>
<xs:element name="ignores" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="ignore" type="xs:string"
maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ignore" type="xs:string"
maxOccurs="unbounded" />
</xs:choice>
</xs:group>
<xs:element name="default">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="for" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:group name="defaults">
<xs:choice>
<xs:element name="defaults" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element ref="default"
maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element ref="default"
minOccurs="0" maxOccurs="unbounded" />
</xs:choice>
</xs:group>
<xs:complexType name="callback">
<xs:sequence>
<xs:group ref="envelope:parameters" />
</xs:sequence>
<xs:attribute name="class" type="types:php_class" />
</xs:complexType>
<xs:complexType name="callbacks">
<xs:sequence>
<xs:element name="callback" type="callback" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:group name="callbacks">
<xs:choice>
<xs:element name="callbacks" type="callbacks"
minOccurs="0" />
<xs:element name="callback" type="callback"
minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:group>
<!-- Routes -->
<xs:complexType name="route">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<!-- Parameters should be explicitly allowed in routes, but if we include
them in the schema it becomes non-deterministic according to libxml.
They are queried by the internal handler, though. -->
<xs:any namespace="##other" processContents="lax"
minOccurs="0" maxOccurs="unbounded" />
<xs:group ref="ignores" />
<xs:group ref="defaults" />
<xs:group ref="routes" />
<xs:group ref="callbacks" />
</xs:sequence>
<xs:attribute name="name" type="route_name" />
<xs:attribute name="pattern" type="xs:string" use="required" />
<xs:attribute name="imply" type="xs:string" />
<xs:attribute name="cut" type="xs:string" />
<xs:attribute name="stop" type="xs:string" />
<xs:attribute name="source" type="xs:string" />
<xs:attribute name="constraint" type="xs:string" />
<!-- Values to be set on match -->
<xs:attribute name="action" type="xs:string" />
<xs:attribute name="locale" type="xs:string" />
<xs:attribute name="method" type="xs:string" />
<xs:attribute name="module" type="xs:string" />
<xs:attribute name="output_type" type="xs:string" />
</xs:complexType>
<xs:complexType name="routes">
<xs:sequence>
<xs:element name="route" type="route" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:group name="routes">
<xs:choice>
<xs:element name="routes" type="routes"
minOccurs="0" />
<xs:element name="route" type="route"
minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:group>
<xs:group name="configuration">
<xs:sequence>
<xs:any namespace="##other" processContents="lax"
minOccurs="0" maxOccurs="unbounded" />
<xs:group ref="routes" />
</xs:sequence>
</xs:group>
</xs:schema>
使用以下 XSL 文件:
routing.xsl
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:routing="http://domain.tld/xml/config/parts/routing"
>
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" />
<xsl:include href="_common.xsl" />
<xsl:variable name="routing" select="'http://domain.tld/xml/config/parts/routing'" />
</xsl:stylesheet>
_common.xsl
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt-common="http://exslt.org/common"
xmlns:saxon="http://icl.com/saxon"
xmlns:envelope="http://framework.youds.com/xml/config/global/envelope"
>
<xsl:variable name="envelope" select="'http://framework.youds.com/xml/config/global/envelope'" />
<!-- callable template for migrating envelope nodes -->
<xsl:template name="_common-migrate-envelope-element">
<!-- param for the target namespace; defaults to 1.0 -->
<xsl:param name="namespace" select="$envelope" />
<!-- attributes to insert, defaults to empty node set -->
<xsl:param name="attributes" select="self::node()[false()]" />
<xsl:call-template name="_common-migrate-element">
<xsl:with-param name="namespace" select="$namespace" />
<xsl:with-param name="attributes" select="$attributes" />
</xsl:call-template>
</xsl:template>
<xsl:template name="_common-migrate-element">
<!-- param for the target namespace; no default -->
<xsl:param name="namespace" />
<!-- attributes to insert, defaults to empty node set -->
<xsl:param name="attributes" select="self::node()[false()]" />
<!-- create an element of the same name -->
<xsl:element name="local-name()" namespace="$namespace">
<!-- also copy all namespace declarations with a prefix (so only xmlns:foo="...", not plain xmlns="..."), except the one of the current element (otherwise, we'd overwrite the namespace in the <element> above if it's just xmlns etc) -->
<!-- the not(name() = '') part is to ensure that we don't copy xmlns="..." declarations, since that might give very strange results and isn't necessary anyway -->
<!-- the purpose of copying these declarations is to make sure that they remain available as originally declared, which usually is only relevant in cases where element or attribute content refers to the declared prefixes again, think <xs:element type="foo:burp" />. We need that mainly for SOAP, WSDL and stuff like that -->
<xsl:copy-of select="namespace::*[not(name() = '') and not(. = namespace-uri(current()))]" />
<xsl:copy-of select="@*" />
<xsl:copy-of select="exslt-common:node-set($attributes)//@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<!-- we need to apply templates to sub-elements, just in case someone wrapped a native youds element and processed that with xsl, for example -->
<!-- so we cannot use copy-of here -->
<!-- node() and the copy will mean that everything is copied, even text nodes etc -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
还有一些其他文件可能与它的处理有关,我在这里包括了这些文件:https://pastebin.com/aynNT2BT
对于我只是不知道从哪里开始的真正笼统的问题道歉!所以基本上最终的 XML 将是 <configurations>...</configurations>
而不是 <ae:configurations>...</ae:configurations>
。
提前致谢
【问题讨论】:
你是问怎么修改xml文件还是怎么修改schema? 修改架构 那么这与 XSLT 有什么关系? 因为我给了XSL文件? 啊。我的错。它为 xslt 自动更正。 【参考方案1】:所以问题已解决,原来是需要解决的 PHP 问题,因为子 <ae:configuration>
等允许为 <configuration>
,父节点必须为 :ae 但没关系。
谢谢
【讨论】:
以上是关于从 XML Schema 中移除命名空间支持的主要内容,如果未能解决你的问题,请参考以下文章
XML XSD 错误:org.xml.sax.SAXParseException:s4s-elt-schema-ns:元素“配置”的命名空间必须来自模式命名空间