XSD 在验证期间忽略名称空间 xsd 导入
XSD ignoring namespace during validation xsd with imports
这个问题我基于简单的例子。
我有 2 XSDs
main.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:sub="urn:xsd:subXSD"
xmlns="urn:xsd:mainXSD"
targetNamespace="urn:xsd:mainXSD"
elementFormDefault="qualified">
<xs:import namespace="urn:xsd:subXSD" schemaLocation="sub.xsd"/>
<xs:element name="main">
<xs:complexType>
<xs:sequence>
<xs:element name="elementA"/>
<xs:element maxOccurs="unbounded" name="subElement" type="sub:SubType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
sub.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:xsd:subXSD"
targetNamespace="urn:xsd:subXSD"
elementFormDefault="qualified">
<xs:complexType name="SubType">
<xs:sequence>
<xs:element name="subA"/>
<xs:element name="subB"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
现在我尝试验证 2 个 xml
withNamespace.xml
<?xml version="1.0" encoding="UTF-8"?>
<main xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sub="urn:xsd:subXSD"
xmlns="urn:xsd:mainXSD"
xsi:schemaLocation="urn:xsd:mainXSD main.xsd
urn:xsd:subXSD sub.xsd">
<elementA>
Element A content
</elementA>
<subElement>
<sub:subA>sub 1 a</sub:subA>
<sub:subB>sub 1 b</sub:subB>
</subElement>
<subElement>
<sub:subA>sub 2 a</sub:subA>
<sub:subB>sub 2 b</sub:subB>
</subElement>
</main>
withoutNamespace.xml
<?xml version="1.0" encoding="UTF-8"?>
<main xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:xsd:mainXSD"
xsi:schemaLocation="urn:xsd:mainXSD main.xsd">
<elementA>
Element A content
</elementA>
<subElement>
<subA>sub 1 a</subA>
<subB>sub 1 b</subB>
</subElement>
<subElement>
<subA>sub 2 a</subA>
<subB>sub 2 b</subB>
</subElement>
</main>
为了验证 xml,我使用了简单的实现:
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.IOException;
public class XSDExample {
public static final String BASE_DIR = "...";
public static void main(String[] args) {
try {
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(new File(BASE_DIR + "main.xsd"));
Validator validator = schema.newValidator();
System.out.println(validate(validator, "withNamespace.xml"));
System.out.println(validate(validator, "withoutNamespace.xml"));
} catch (SAXException | IOException e) {
e.printStackTrace();
}
}
private static String validate(Validator validator, String fileName) throws IOException {
System.out.println(fileName);
try {
validator.reset();
validator.validate(new StreamSource(new File(BASE_DIR + fileName)));
} catch (SAXException e) {
return e.getMessage();
} catch (IOException e) {
throw e;
}
return "Valid";
}
}
这段代码的执行输出:
withNamespace.xml
Valid
withoutNamespace.xml
cvc-complex-type.2.4.a: Invalid content was found starting with element 'subA'. One of '{"urn:xsd:subXSD":subA}' is expected.
是否可以创建一个 XSD 来验证 XML 文件是否带有导入的 XSD 架构命名空间?
或者可能有 javax.xml.validation.Validator 配置来跳过名称空间检查?
It is possible to create one XSD that will allow me to verify XML
files with and without the imported XSD schema namespace?
没有,没有。
您可以做的是在模式验证之前将两个输入(使用 XSLT)转换为通用格式。将规范化转换作为验证管道的第一步是一项非常有价值的技术,但还不够广为人知。
这个问题我基于简单的例子。 我有 2 XSDs
main.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:sub="urn:xsd:subXSD"
xmlns="urn:xsd:mainXSD"
targetNamespace="urn:xsd:mainXSD"
elementFormDefault="qualified">
<xs:import namespace="urn:xsd:subXSD" schemaLocation="sub.xsd"/>
<xs:element name="main">
<xs:complexType>
<xs:sequence>
<xs:element name="elementA"/>
<xs:element maxOccurs="unbounded" name="subElement" type="sub:SubType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
sub.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:xsd:subXSD"
targetNamespace="urn:xsd:subXSD"
elementFormDefault="qualified">
<xs:complexType name="SubType">
<xs:sequence>
<xs:element name="subA"/>
<xs:element name="subB"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
现在我尝试验证 2 个 xml
withNamespace.xml
<?xml version="1.0" encoding="UTF-8"?>
<main xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sub="urn:xsd:subXSD"
xmlns="urn:xsd:mainXSD"
xsi:schemaLocation="urn:xsd:mainXSD main.xsd
urn:xsd:subXSD sub.xsd">
<elementA>
Element A content
</elementA>
<subElement>
<sub:subA>sub 1 a</sub:subA>
<sub:subB>sub 1 b</sub:subB>
</subElement>
<subElement>
<sub:subA>sub 2 a</sub:subA>
<sub:subB>sub 2 b</sub:subB>
</subElement>
</main>
withoutNamespace.xml
<?xml version="1.0" encoding="UTF-8"?>
<main xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:xsd:mainXSD"
xsi:schemaLocation="urn:xsd:mainXSD main.xsd">
<elementA>
Element A content
</elementA>
<subElement>
<subA>sub 1 a</subA>
<subB>sub 1 b</subB>
</subElement>
<subElement>
<subA>sub 2 a</subA>
<subB>sub 2 b</subB>
</subElement>
</main>
为了验证 xml,我使用了简单的实现:
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.IOException;
public class XSDExample {
public static final String BASE_DIR = "...";
public static void main(String[] args) {
try {
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(new File(BASE_DIR + "main.xsd"));
Validator validator = schema.newValidator();
System.out.println(validate(validator, "withNamespace.xml"));
System.out.println(validate(validator, "withoutNamespace.xml"));
} catch (SAXException | IOException e) {
e.printStackTrace();
}
}
private static String validate(Validator validator, String fileName) throws IOException {
System.out.println(fileName);
try {
validator.reset();
validator.validate(new StreamSource(new File(BASE_DIR + fileName)));
} catch (SAXException e) {
return e.getMessage();
} catch (IOException e) {
throw e;
}
return "Valid";
}
}
这段代码的执行输出:
withNamespace.xml
Valid
withoutNamespace.xml
cvc-complex-type.2.4.a: Invalid content was found starting with element 'subA'. One of '{"urn:xsd:subXSD":subA}' is expected.
是否可以创建一个 XSD 来验证 XML 文件是否带有导入的 XSD 架构命名空间? 或者可能有 javax.xml.validation.Validator 配置来跳过名称空间检查?
It is possible to create one XSD that will allow me to verify XML files with and without the imported XSD schema namespace?
没有,没有。
您可以做的是在模式验证之前将两个输入(使用 XSLT)转换为通用格式。将规范化转换作为验证管道的第一步是一项非常有价值的技术,但还不够广为人知。