0

Infrastructure: I'm using JAVA 1.5 and this is mandatory. But i can load any external lib so no problem.

Problem:

I have an XML file recived via "an external channel" and I can use it as InputStream

if someone need to get the same, could use:

InputStream is = new FileInputStream(file);

I need to validate the XML against XSD that has neasted XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           xmlns:BODY="urn:CBI:xsd:CBIBdySDDReq.00.00.06" 
           xmlns:HTRT="urn:CBI:xsd:CBIHdrTrt.001.07" 
           xmlns:HE2E="urn:CBI:xsd:CBIHdrSrv.001.07" 
           xmlns:SGNT="urn:CBI:xsd:CBISgnInf.001.04" 
           xmlns:LMSG="urn:CBI:xsd:CBISDDReqLogMsg.00.00.06"
           xmlns="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06"
           targetNamespace="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06"
           elementFormDefault="qualified">
    <xs:import namespace="urn:CBI:xsd:CBIHdrTrt.001.07" schemaLocation="CBIHdrTrt.001.07.xsd"/>
    <xs:import namespace="urn:CBI:xsd:CBIHdrSrv.001.07" schemaLocation="CBIHdrSrv.001.07.xsd"/>
    <xs:import namespace="urn:CBI:xsd:CBIBdySDDReq.00.00.06" schemaLocation="CBIBdySDDReq.00.00.06.xsd"/>
    <xs:element name="CBISDDReqPhyMsg" type="CBISDDReqPhyMsg.00.00.06">
        <xs:annotation>
            <xs:documentation>1. - Tag root dell'intero messaggio fisico di richiesta SDD CBI</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:complexType name="CBISDDReqPhyMsg.00.00.06">
        <xs:sequence>
            <xs:element name="CBIHdrTrt" type="HTRT:CBIHdrTrt.001.07">
                <xs:annotation>
                    <xs:documentation>1.1. - Header di tratta CBI</xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="CBIHdrSrv" type="HE2E:CBIHdrSrv.001.07">
                <xs:annotation>
                    <xs:documentation>1.2. - Header di servizio CBI</xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="CBIBdySDDReq" type="BODY:CBIBdySDDReq.00.00.06">
                <xs:annotation>
                    <xs:documentation>1.3. - Body di servizio CBI</xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

So I have a brunch of XSD file.

A chunk XML file is this

<?xml version="1.0" encoding="UTF-8"?>
<MSG:CBISDDReqPhyMsg xmlns:MSG="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06"
    xmlns:HTRT="urn:CBI:xsd:CBIHdrTrt.001.07" xmlns:HE2E="urn:CBI:xsd:CBIHdrSrv.001.07"
    xmlns:BODY="urn:CBI:xsd:CBIBdySDDReq.00.00.06" xmlns:LMSG="urn:CBI:xsd:CBISDDReqLogMsg.00.00.06"
    xmlns:SGNT="urn:CBI:xsd:CBISgnInf.001.04" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <MSG:CBIHdrTrt>
        <HTRT:IdCBISndrf>0000636J</HTRT:IdCBISndrf>
        <HTRT:IdCBIRcvrf>0000641V</HTRT:IdCBIRcvrf>
        <HTRT:SrvNm>INC-SDDC</HTRT:SrvNm>
        <HTRT:IdMsgTrt>
            0000636JP12312111154007381042010010000636J000000636J0000641V0
        </HTRT:IdMsgTrt>

So i need to validate the XML against CBISDDReqPhyMsg.00.00.06. So i know only at runtime against wich xml to use. Example another file could load CBISDDReqPhyMsg.00.00.05

I have two major problem

1) I need to obtain the xsd file name from XML and XML could be BIG 1/2GB (stax/sax are a nice solution)

2) I need to load the xsd from a jar because the whole app cannot have access to the file system.

For validation i prefer a system like http://www.edankert.com/validate.html

I read about include in this answer Problem validating an XML file using Java with an XSD having an include

But using the loader i can't obtain the infos about file.

Some idea?

4

1 回答 1

2

我有两个主要问题

1) 我需要从 XML 中获取文件名,XML 可能是 BIG 1/2GB

2)我需要从 jar 加载 xsd,因为整个应用程序无法访问文件系统。

1.) 文件名不在 XML 中...您应该通过其他方式(用户输入、硬编码等)知道 XML 的文件名是什么。如果您有一个仅包含 XML 文件的目录,则可以对这些文件运行循环。一些伪代码:

for(getNextFile)
{
    if(xmlValidationWithXSD(nextFile))
        //passed validation
    else
        //failed validation
}

我通常运行脚本将所有 XML 文件从一个位置移动到仅 XML 文件夹。

2.) 我相信 StreamSource 允许你这样做。这是我最近所做的:

            public static boolean xmlValidationWithXSD(String xmlLocation){
                Source xmlFile = new StreamSource(new File(xmlLocation));

                 //IMPORTANT:  Here is what you need.  Multiple XSDs (that relate to each other) AND getResource will access form .jar files
                //Treat XSD as resource found in the class path, assume that the full package name is passed in xsdLocation
                Source schemaFileSource1 = new StreamSource(BenefitEnrollmentRequestFileUtil.class.getResource(NEW_XSD_FILE_RESOURCE1).toString());
                Source schemaFileSource2 = new StreamSource(BenefitEnrollmentRequestFileUtil.class.getResource(NEW_XSD_FILE_RESOURCE2).toString());
                Source[] schemaFileSources = {schemaFileSource1, schemaFileSource2};  


                SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

                try {
                    Schema schema = schemaFactory.newSchema(schemaFileSources);
                    Validator validator = schema.newValidator();
                    validator.validate(xmlFile);
                    return true;
                } catch (SAXException e) {
                    LOGGER.debug(xmlFile.getSystemId() + " is NOT valid", e);
                    LOGGER.debug("Reason: " + e.getLocalizedMessage());
                } catch (IOException e) {
                    LOGGER.debug(xmlFile.getSystemId() + " is NOT valid", e);
                    LOGGER.debug("Reason: " + e.getLocalizedMessage());                 
                }
                return false;
            }

资料来源:

在 jar 文件中引用 XSD 架构

使用带有包含包含的 XSD 的 Java 验证 XML 文件时出现问题

编辑:

文件之间的关系是第一个标签中包含的列表我有要使用的 xsd 列表,第一个 xsd 是与第一个标签具有相同名称的那个

<MSG:CBISDDReqPhyMsg xmlns:MSG="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06" xmlns:HTRT="urn:CBI:xsd:CBIHdrTrt.001.07" xmlns:HE2E="urn:CBI:xsd:CBIHdrSrv.001.07" xmlns:BODY="urn:CBI:xsd:CBIBdySDDReq.00.00.06" xmlns:LMSG="urn:CBI:xsd:CBISDDReqLogMsg.00.00.06" xmlns:SGNT="urn:CBI:xsd:CBISgnInf.001.04" xmlns:xsi="w3.org/2001/XMLSchema-instance">;

你不能读第一行,然后提取数据吗?使用 FileReader/DOM(如果您只是阅读一行,它不应该太慢)只是为了检索这一行。然后解析字符串。创建一个 ArrayList 并添加您提取的每个单独的部分。

就效率而言,检查一下:

https://stackoverflow.com/a/2134533/2498729

https://stackoverflow.com/a/12273296/2498729

于 2013-08-07T13:37:17.847 回答