如何使用XML Schema重用另一个Schema / Namespace(即XHTML)中的元素?

时间:2015-03-05 11:05:26

标签: xml xhtml schema xml-namespaces xsd-validation

我试图定义一个Schema,它允许在某些地方使用特定的(X)HTML元素。我遇到的问题是Schema编译失败。

这是Schema:

<?xml version="1.0"?>
<xs:schema
    xmlns:html="http://www.w3.org/1999/xhtml"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>

    <xs:import
        namespace="http://www.w3.org/1999/xhtml"
        schemaLocation="http://www.w3.org/MarkUp/Schema/xhtml11.xsd"
    />

    <xs:element name="foo">
        <xs:complexType>
            <xs:sequence>
                <xs:element
                    ref="html:blockquote"
                    minOccurs="0"
                    maxOccurs="unbounded"
                />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

这是XML文件:

<foo xmlns:html="http://www.w3.org/1999/xhtml">
    <html:blockquote>The quick brown fox jumped over the lazy dog.</html:blockquote>
</foo>

这是我收到的错误消息:

christian@armor01:~/testCase$ xmllint -schema foo.xsd -noout foo.xml
foo.xsd:12: element element: Schemas parser error : Element \
'{http://www.w3.org/2001/XMLSchema}element', attribute 'ref': The QName value \
'{http://www.w3.org/1999/xhtml}blockquote' does not resolve to a(n) element \
declaration.
WXS schema foo.xsd failed to compile

我理解错误消息的含义,但我不明白错误发生的原因。错误消息意味着当我提到blockquote时,它找不到blockquote。但我不明白为什么会发生这种错误,因为我导入了XHTML 1.1架构。

我还试图找出这是否是xmllint特有的问题。所以我写了一个小程序来执行Schema验证,但我基本上得到了同样的错误。

这是Java程序:

import java.io.*;
import java.net.*;
import javax.xml.*;
import javax.xml.parsers.*;
import javax.xml.validation.*;
import org.w3c.dom.*;

public class Validate {
    public static void main(final String... args) throws Exception {
        final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        //dbf.setValidating(true);
        dbf.setSchema(schemaFactory.newSchema(new File(args[0]).toURI().toURL()));
        final DocumentBuilder db = dbf.newDocumentBuilder();
        final Document doc = db.parse(args[1]);
    }
}

这是我从该计划中获得的错误:

christian@armor01:~/testCase$ java Validate foo.xsd foo.xml
Exception in thread "main" org.xml.sax.SAXParseException; \
systemId: file:/home/christian/testCase/foo.xsd; \
lineNumber: 12; \
columnNumber: 88; \
src-resolve: Cannot resolve the name 'html:blockquote' to a(n) 'element declaration' component.

很明显,我在Schema中做错了什么 - 但是什么? 定义Schema(对于没有名称空间的目标语法)的正确方法是什么,它重用来自另一个Schema / Namespace的元素,如XHTML?

BTW我也试过<xs:include/>但这对我来说似乎不合适,但它失败了,因为它要求包含架构和包含的架构以相同的命名空间为目标。

1 个答案:

答案 0 :(得分:1)

似乎“blockquote”元素未定义为全局元素,因此您无法直接引用它。 如果您查看xhtml架构http://www.w3.org/MarkUp/SCHEMA/xhtml11-model-1.xsd的子部分,您会注意到它的类型为xhtml.blockquote.type

所以解决方法是声明你的blockquote如下:

<xs:schema xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:import namespace="http://www.w3.org/1999/xhtml" schemaLocation="http://www.w3.org/MarkUp/Schema/xhtml11.xsd"/>
        <xs:element name="foo">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="blockquote" type="html:xhtml.blockquote.type" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

以及这个有效的XML实例:

<?xml version="1.0"?>
<foo xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">
    <blockquote><html:p>quick brown fox jumped over the lazy dog.</html:p></blockquote>
</foo>

您会注意到blockquote元素未绑定到html命名空间。 由于您导入了其他名称空间的元素,我认为将默认目标名称空间设置为您自己的元素也是一种更好的做法。