6

Here's the scenario:

I bundled several .xml (somewhat of a configuration) files needed for my application to run in an .jar file. The jar file has the following structure:

settings-1.0.0.jar
˪ resources/
  ˪ 1.xml
  ˪ 2.xml
  ˪ 3.xml
˪ META-INF/
  ˪ MANIFEST.MF

1.xml has the following content:

<?xml version="1.0" encoding="UTF-8"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
    <!-- Include 2 -->
    <xi:include
        href="resource:resources/2.xml" />
    <!-- Include 3 -->
    <xi:include
        href="resource:resources/3.xml" />
    <!--
    <map>
    </map>
    -->
</document>

based on this article. When trying to access these includes (after successfully deploying my application) I get the following error:

Caused by: org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 43; An 'include' failed, and no 'fallback' element was found.
    at org.apache.xerces.parsers.DOMParser.parse(DOMParser.java:245)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:298)
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
    at org.zcore.dkp.backend.mapper.MappingParser.parse(MappingParser.java:60)
    ... 327 more

I tried(&error'd) all thinkable options. What's the right combination for xi:include'ing an .xml file in a jar-file installed as WildFly module?

Edit: Here's how the xmlfile is loaded:

private void loadBackendMapping() {
    try {
        BackendMappingParser parser = new BackendMappingParser();
        InputStream in = ResourceLoaderHelper.getResourceAsStream(BACKEND_MAPPING_RESOURCE);
        if (in == null) {
            throw new FileNotFoundException();
        }
        try {
            parser.parse(in);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                log.warn("Failed to close " + BACKEND_MAPPING_RESOURCE, e);
            }
        }
        backendMapping = parser.getMapping();
        if (log.isDebugEnabled()) {
            log.debug(BACKEND_MAPPING_RESOURCE + " successfully loaded!");
        }
    } catch (FileNotFoundException e) {
        log.warn("\"" + BACKEND_MAPPING_RESOURCE + "\" not found!");
        backendMapping = new BackendMapping();
    } catch (Exception e) {
        throw new CenterwareSystemException("Failed to parse " + BACKEND_MAPPING_RESOURCE, e);
    }
}

BACKEND_MAPPING_RESOURCE contains the filename (1.xml).

Robert Heine
  • 1,820
  • 4
  • 29
  • 61
  • What is your use case? Is it really necessary to package your settings in a jar file? –  Apr 21 '17 at 20:57
  • http://stackoverflow.com/questions/8412798/how-to-load-xmlcatalog-from-classpath-resources-inside-a-jar-reliably See if it helps –  Apr 22 '17 at 06:10
  • 1
    Can you show the code that you use for creating parser/mapper? – Tomaz Cerar Apr 26 '17 at 13:52
  • @ctomc Sorry, didn't notice your comment. :-/ Added how the `1.xml` is loaded programmatically. – Robert Heine Jun 14 '17 at 09:56

2 Answers2

2

It depends on your XML parser.

As per your exception it seems you use SAX.
Try this article: https://www.ibm.com/developerworks/library/x-tipentres/

The above document uses the SAX API's EntityResolver interface for locating resources in an XML document.

Usagi Miyamoto
  • 6,196
  • 1
  • 19
  • 33
1

Remove the "resource:" prefix from your URLs, as this seems to be a JBoss specific protocol.

Also emit the "resource/" path, as 1.xml, 2.xml and 3.xml all reside in the same folder and you usually specify relative path (from 1 to 2 and from 1 to 3).

Try the following:

<?xml version="1.0" encoding="UTF-8"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
    <!-- Include 2 -->
    <xi:include href="2.xml" />
    <!-- Include 3 -->
    <xi:include href="3.xml" />
    <!--
    <map>
    </map>
    -->
</document>
potame
  • 7,597
  • 4
  • 26
  • 33
Philip Helger
  • 1,814
  • 18
  • 28
  • What is the "relative path" of a stream? Not all XML documents come from a real file system... – Usagi Miyamoto Apr 24 '17 at 08:05
  • The relative path is e.g. "resource" in the file listing on top. If you manage to get 1.xml loaded, 2.xml and 3.xml must be adressed relative to 1.xml -> so without any folder (when following the structure given in the question) – Philip Helger Apr 24 '17 at 09:43
  • The XML parser does not know this. It gets a `Document`, or a character stream, or some other source it can read characters from. – Usagi Miyamoto Apr 24 '17 at 12:47
  • 2
    If you additionally fill in the "SystemID" and an "EntityResolver" it can figure out the location of relative resources automatically. – Philip Helger Apr 25 '17 at 12:15