限制XML中的标记插入

时间:2014-03-10 05:39:26

标签: java xml dom xsd jaxp

我的问题与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);

}

}

2 个答案:

答案 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