проверка XML-документа в исходном коде oracle на Java

#java #xml #oracle #validation #xml-validation

#java #xml #Oracle #проверка #xml-проверка

Вопрос:

Пытаюсь выполнить subject.

Я пытаюсь использовать xsd из file (schemasource = 1) и из clob (schemasource = 0). У меня есть две схемы xsd common_types.xsd и migom.xsd. вторая включает первую. Проблема в том, что когда я использую схему common_types из файла, я получаю ошибку

ORA-29532: вызов Java завершен из-за неперехваченного исключения Java: исключение oracle.xml.parser.v2.XMLParseException: возникла внутренняя ошибка.

и когда я проверяю xml на соответствие только первой схеме, прочитанной из clob, я получаю успех, но когда я добавляю второй xsd, я получаю ту же ошибку, которая вообще ничего не говорит.

 create or replace and compile java source named XmlTools AS
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;

import org.xml.sax.InputSource;
import oracle.sql.CLOB;
import java.io.IOException;
import org.xml.sax.SAXException;
import java.sql.SQLException;
import java.lang.IllegalArgumentException;
import oracle.xml.parser.v2.XMLParseException;
import javax.xml.parsers.ParserConfigurationException;

import java.io.*;

public class XmlValidator
{

  static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
  static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; 
  static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";


  public static void ValidateDocument(int schemasource, oracle.sql.CLOB schemadoc, oracle.sql.CLOB schemadoc1, oracle.sql.CLOB xmldoc) throws SAXException, IOException, SQLException, ParserConfigurationException, XMLParseException, IllegalArgumentException {


    try
          {              

            File myfile = new File(".//XML//common_types.xsd");
            if (myfile.exists())
            {
                Serv.log("ValidateDocument", "file size"   Long.toString(myfile.length()));
            }
            /*else
            {
                Serv.log("ValidateDocument", "file doesn't exists" );
            }*/

            Serv.log("ValidateDocument", "1" );
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setValidating(true);
            factory.setNamespaceAware(true);

            Serv.log("ValidateDocument", "2" );        
            SAXParser saxParser = factory.newSAXParser();
            saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);

            if (schemasource == 0)
            {
                InputSource schemaIs = new InputSource(schemadoc.getCharacterStream());        
                InputSource schemaIs1 = new InputSource(schemadoc1.getCharacterStream());  

                InputSource[] schemas = {schemaIs, schemaIs1};

                //saxParser.setProperty(JAXP_SCHEMA_SOURCE,   schemaIs); 
                saxParser.setProperty(JAXP_SCHEMA_SOURCE,   schemas); 
            }
            else
            {            
                saxParser.setProperty(JAXP_SCHEMA_SOURCE,   ".//XML//common_types.xsd"); 
            }
            XMLReader reader = saxParser.getXMLReader();

            //Получаем входной XML документ
            InputSource documentIs = new InputSource(xmldoc.getCharacterStream());
            Serv.log("ValidateDocument", "3" );          
            //Запуск разбора
            reader.parse(documentIs);
            Serv.log("ValidateDocument", "4" );          
            documentIs = null;     

           }
    /*catch (SAXException e) 
    {
        Serv.log("ValidateDocument", "SAXException" );
        Serv.log("ValidateDocument", "document is not valid because ");
        Serv.log("ValidateDocument", e.getMessage());
        throw(e);
    }*/          
    catch (ParserConfigurationException e) 
    {
        Serv.log("ValidateDocument", "ParserConfigurationException" );
        throw(e);
    }
    catch (IOException e) 
    {
        Serv.log("ValidateDocument", "IOException" );        
        throw(e);
    }

    catch (XMLParseException e)
    {
        Serv.log("ValidateDocument", "XMLParseException" );        
        Serv.log("ValidateDocument", e.getMessage());
        StackTraceElement[] stack = e.getStackTrace();        
        for (int i = 0; i < stack.length; i  )
        {
         Serv.log("stacktrace element no "   Integer.toString(i), "toString: "   stack[i].toString());
         Serv.log("stacktrace element no "   Integer.toString(i), "file name: "   stack[i].getFileName()   ", class name: "   stack[i].getClassName()   ", method name: "   stack[i].getMethodName()   ", line : "   stack[i].getLineNumber());
        }

        throw(e);
    }
    catch (IllegalArgumentException e)
    {
        Serv.log("ValidateDocument", "IllegalArgumentException" );        
        Serv.log("ValidateDocument", e.getMessage());
        throw(e);    
    }           


    }

}
  

дополнительная информация получена из java stacktrace:

имя файла: XMLError.java , имя класса: oracle.xml.parser.v2.XMLError, имя метода: flushErrors1, строка: 320 имя файла: NonValidatingParser.java , имя класса: oracle.xml.parser.v2.NonValidatingParser, имя метода: parseDocument, строка: 300 имя файла: XMLParser.java , имя класса:oracle.xml.parser.v2.XMLParser, имя метода: parse, строка: 200 имя файла: XMLTOOLS, имя класса: XmlValidator, имя метода: ValidateDocument, строка: 86

моей версией oracle является Oracle Database 10g Enterprise Edition версии 10.2.0.1.0 — Prod, но моя цель — заставить его работать на всех версиях, начиная с 9

Ответ №1:

Обновить:

итак, вы загрузили эти файлы в базу данных как CLOBs. соблюдали ли вы их кодировку xml, когда вставляли их в базу данных?

Комментарии:

1. не помогло. я могу сказать, что если я объединю эти две схемы в одну и помещу ее как clob, это приведет к той же ошибке. и из-за этого я думаю, что дело во втором xsd, но я не могу выяснить, что именно! все схемы — две автономные и объединенная — правильно сформированы и действительны (проверено в altova xmlspy)

2. да, я указал кодировку в величает файлов <?xml version=»1.0″ encoding=»windows-1251″?>

3. правильно, и вы использовали эту кодировку, когда преобразовывали их в строки и вставляли в базу данных?

4. Да, я загружаю содержимое файла в правильной кодировке. Пробовал кодовые страницы Windows-1251 и utf-8.

5. Просто для ясности: ваша база данных настроена на использование той же кодировки, что и вставляемая строка? В противном случае Oracle не сможет правильно интерпретировать содержимое Clob. Я не дома с Oracle, который, похоже, использует переменные среды NLS, но в MySQL это параметр для создания базы ДАННЫХ.

Ответ №2:

Согласно вашему stacktrace, я увидел, что использовался NonValidatingParser. Несмотря на то, что вы не упомянули об этом как о проблеме, это было неожиданно. Я знаю, что в xmlparserv 2 есть проверяющий синтаксический анализатор, поэтому я взглянул на декомпилированный XMLParser в xmlparserv2.jar (Он у меня с собой, так как я работаю над OC4J).

Декомпилированный исходный код приведен ниже. Как вы можете видеть, конструктор по умолчанию использует синтаксический анализатор без проверки. Использование setProperty должно переключить его на ValidatingParser, но поскольку этого не происходит.

 XMLParser()
{
    parser = new NonValidatingParser();
}
  

Я не смог найти метод setProperty в декомпилированном коде. Это необычно, но я не изучал это. Я полагаю, вам придется использовать другой метод API, чтобы включить проверку xml. Я считаю, что метод setAttribute будет делать то, что вы хотите.

public void setAttribute(String s, Object obj) вызывает исключение IllegalArgumentException {

     ............
    if(s == "http://java.sun.com/xml/jaxp/properties/schemaSource")
        schemaSource = obj;
    else
    if(s == "http://java.sun.com/xml/jaxp/properties/schemaLanguage")
    {
        if(((String)obj).equals("http://www.w3.org/2001/XMLSchema"))
            setValidationMode(3);
        getSchemaValidator().setJAXP(true);
    }
    .......................
    attributes.put(s, obj);
}
  

Я использовал его в приложении, развернутом на OC4J, которое, как я знаю, использует тот же синтаксический анализатор.
Пример кода показан ниже

Фабрика DocumentBuilderFactory = DocumentBuilderFactory.newInstance();

factory.setNamespaceAware(true);

factory.setValidating(истина);

factory.setAttribute(«http://java.sun.com/xml/jaxp/properties/schemaLanguage «, «http://www.w3.org/2001/XMLSchema «);

factory.setAttribute(«http://java.sun.com/xml/jaxp/properties/schemaSource «, ClassUtil.getResourceAsStream(schemaSourceLocation));

Надеюсь, это поможет.