我的问题与Java有关。我有一个最初根据xsd有效的xml,我使用了DOM解析器并从中获取了一个Document对象(我正在使用JAXP)。现在,我想禁止插入无效的xml元素。所以,当我尝试像appendChild()这样的东西时,如果元素按照模式无效,我应该得到一个异常。
我在获取dom之前已将模式设置为工厂级别。但是,插入无效元素似乎没问题。当我使用验证api来检查Document的有效性时,我才知道我的文档是不正确的,但最终会发生这种情况。
这是XML
<?xml version="1.0" encoding="UTF-8"?>
<Company xmlns="uri:Trial">
<Business>
<APAC>tns:APAC</APAC>
</Business>
<NonBusiness>
<Facilities>tns:Facilities</Facilities>
</NonBusiness>
</Company>
xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="uri:Trial"
xmlns:tns="uri:Trial" elementFormDefault="qualified" attributeFormDefault="qualified">
<element name="Company" type="tns:MyComplexType"></element>
<complexType name="MyComplexType">
<sequence>
<element ref="tns:Business"></element>
<element ref="tns:NonBusiness"></element>
</sequence>
</complexType>
<element name="Business" type="tns:BusinessType"></element>
<element name="APAC" type="string"></element>
<element name="AUS" type="string"></element>
<element name="NonBusiness" type="tns:NonBusinessType"></element>
<element name="Facilities" type="string"></element>
<complexType name="BusinessType">
<choice>
<element ref="tns:APAC"></element>
<element ref="tns:AUS"></element>
</choice>
</complexType>
<complexType name="NonBusinessType">
<sequence>
<element ref="tns:Facilities"></element>
</sequence>
</complexType>
</schema>
java
公共类MainJAXPValidation {
public static void main(String[] args) throws Exception {
File fxml = new File ("xmls/Trial.xml");
File fxsd = new File ("xmls/Trial.xsd");
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new StreamSource(fxsd));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setSchema(schema);
dbf.setNamespaceAware(true);
// dbf.setValidating(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(fxml);
Node tempNode = doc.createElement("SomeChild");
doc.appendChild(tempNode);
DOMSource ds = new DOMSource(doc);
Validator validator = schema.newValidator();
validator.validate(ds);
}
}
答案 0 :(得分:0)
我可以建议替代方案...... 有一个自定义类说,MyDocument扩展了DocumentImpl。 在您的类中,重写appendChild和其他必要的方法。 在重写的方法中,您可以执行验证并抛出运行时异常。
import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
public class MyDocument extends DocumentImpl{
Document document;
Schema schema;
public MyDocument(File xmlFile,File schemaFile) throws SAXException, IOException, ParserConfigurationException {
this.document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
this.schema = sf.newSchema(new StreamSource(schemaFile));
}
@Override
public Node appendChild(Node newChild) throws DOMException {
//Validation
return super.appendChild(newChild);
}
}
答案 1 :(得分:0)
实际上,有一种方法可以在JAXP中实现。使用DOM,每个Node
也是EventTarget
,因此您可以向EventListener
注册Document
并从那里开始工作(如果是,您的听众可能会抛出异常不允许插入)。
当然,出于性能原因,您可能希望将EventListener
附加到比整个文档更窄的“范围”。
这是一个很好的起点:http://docs.oracle.com/javase/7/docs/api/index.html?org/w3c/dom/events/EventListener.html