in src/main/java/org/apache/maven/xinclude/stax/XIncludeStreamReader.java [145:467]
private void processInclude() throws XMLStreamException {
Location startLocation = this.getLocation();
Element node;
try {
Document doc =
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
DOMResult res = new DOMResult(doc);
XMLEventWriter xew = outputFactory.createXMLEventWriter(res);
XMLEventReader xer = factory.createXMLEventReader(new FragmentReader(getDelegate()));
xew.add(xer);
node = doc.getDocumentElement();
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
String href = getAttribute(node, "href");
String parse = getAttribute(node, "parse");
String xpointer = getAttribute(node, "xpointer");
String fragid = getAttribute(node, "fragid");
String setXmlId = getAttribute(node, "set-xml-id");
String encoding = getAttribute(node, "encoding");
IOException resourceError = null;
if (href == null) {
if (xpointer == null && fragid == null) {
throw new XMLStreamException("xpointer or fragid must be used as href is null");
}
href = "";
} else if (href.contains("#")) {
throw new XMLStreamException("fragment identifiers must not be used in href: " + href);
}
URI hrefUri;
try {
hrefUri = new URI(href);
} catch (URISyntaxException e) {
throw new XMLStreamException("invalid syntax for href: " + href, e);
}
Source input;
String currentLocation = xmlBases.peek();
XMLResolver r = factory.getXMLResolver();
Object o = r != null ? r.resolveEntity(null, href, currentLocation, null) : null;
if (o instanceof URI) {
try {
o = new Stax2URLSource(((URI) o).toURL());
} catch (MalformedURLException e) {
throw new XMLStreamException(e);
}
}
if (o != null && !(o instanceof Source)) {
throw new XMLStreamException(
"Unsupported input of class " + o.getClass().getName());
}
if (o == null) {
resourceError = new IOException("Unable to load resource: " + href);
}
input = (Source) o;
boolean isXml = false;
boolean isText = false;
if (resourceError == null) {
if (parse == null || "xml".equals(parse) || "application/xml".equals(parse) || parse.endsWith("+xml")) {
isXml = true;
} else if ("text".equals(parse) || parse.startsWith("text/")) {
isText = true;
if (xpointer != null) {
throw new XMLStreamException("xpointer cannot be used with text parsing");
}
} else {
resourceError = new IOException("Unsupported media type: " + parse);
}
}
boolean fallback = true;
if (resourceError == null && isXml) {
boolean reportPrologWs = (boolean) factory.getProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE);
if (reportPrologWs) {
factory.setProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE, false);
}
XMLStreamReader reader = factory.createXMLStreamReader(input);
String pointer = xpointer != null ? xpointer : fragid;
try {
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.newDocument();
DOMResult res = new DOMResult(doc);
XMLEventWriter xew = outputFactory.createXMLEventWriter(res);
XMLEventReader xer = factory.createXMLEventReader(reader);
DTD dtd = null;
while (xer.hasNext()) {
XMLEvent event = xer.nextEvent();
if (event instanceof DTD) {
dtd = (DTD) event;
} else {
xew.add(event);
}
}
Element resNode;
if (pointer != null) {
DOMXMLElementEvaluator evaluator = new DOMXMLElementEvaluator(
new XPointer(pointer),
doc.getDocumentElement(),
dtd != null ? (DTDSubset) dtd.getProcessedDTD() : null);
resNode = evaluator.evaluateElement();
} else {
resNode = doc.getDocumentElement();
}
if (resNode != null) {
// xml:lang fix
String curLang = this.xmlLangs.peek();
String impLang = "";
Element p = resNode;
while (p != null) {
Attr attr = p.getAttributeNodeNS(XML_NS_URI, "lang");
if (attr != null) {
impLang = attr.getValue();
break;
}
Node np = p.getParentNode();
p = np instanceof Element ? (Element) np : null;
}
if (!Objects.equals(curLang, impLang)) {
resNode.setAttributeNS(XML_NS_URI, "xml:lang", impLang);
}
resNode.setAttributeNS(XML_NS_URI, "xml:base", input.getSystemId());
NamespaceContext context =
this.contextStack.peek().getReader().getNamespaceContext();
Map<String, String> namespaces = getAllNamespaces(resNode.getParentNode());
for (Map.Entry<String, String> entry : namespaces.entrySet()) {
String prefix = entry.getKey();
String uri = entry.getValue();
if (context != null
&& context.getNamespaceURI(prefix) != null
&& !uri.equals(context.getNamespaceURI(prefix))) {
resNode.setAttributeNS(
XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
prefix.isEmpty() ? "xmlns" : "xmlns:" + prefix,
uri);
}
}
NamedNodeMap attrs = node.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Attr att = (Attr) attrs.item(i);
String ns = att.getNamespaceURI();
if (ns != null && !XML_NS_URI.equals(ns)) {
if ("http://www.w3.org/2001/XInclude/local-attributes".equals(ns)) {
resNode.setAttribute(att.getLocalName(), att.getValue());
} else {
resNode.setAttributeNS(ns, att.getPrefix() + ":" + att.getLocalName(), att.getValue());
}
}
}
if (setXmlId != null) {
resNode.setAttributeNS(XML_NS_URI, "xml:id", setXmlId);
}
XMLStreamReader sr = factory.createXMLStreamReader(new DOMSource(resNode));
pushContext(input.getSystemId(), sr);
fallback = false;
}
} catch (InvalidXPointerException | ParserConfigurationException e) {
throw new XMLStreamException(e);
}
} else if (resourceError == null && isText) {
try {
StringWriter sw = new StringWriter();
Reader reader;
if (input instanceof StreamSource) {
StreamSource ss = (StreamSource) input;
reader = ss.getReader();
if (reader == null) {
InputStream is = ss.getInputStream();
reader = new InputStreamReader(is, encoding != null ? encoding : "UTF-8");
}
} else if (input instanceof Stax2Source) {
Stax2Source ss = (Stax2Source) input;
reader = ss.constructReader();
if (reader == null) {
InputStream is = ss.constructInputStream();
reader = new InputStreamReader(is, encoding != null ? encoding : "UTF-8");
}
} else {
throw new XMLStreamException(
"Unsupported source of class " + input.getClass().getName());
}
transferTo(reader, sw);
String include;
if (fragid != null) {
String scheme;
String integrity;
int scIdx = fragid.indexOf(';');
if (scIdx > 0) {
scheme = fragid.substring(0, scIdx);
integrity = fragid.substring(scIdx + 1);
} else {
scheme = fragid;
integrity = "";
}
if (scheme.startsWith("char=")) {
String str = scheme.substring("char=".length());
int idx = str.indexOf(',');
int min, max;
if (idx >= 0) {
min = idx == 0 ? 0 : Integer.parseInt(str.substring(0, idx));
max = idx == str.length() - 1 ? str.length() - 1 : Integer.parseInt(str.substring(idx + 1));
} else {
min = Integer.parseInt(str);
max = min;
}
include = sw.toString().substring(min, max);
} else if (scheme.startsWith("line=")) {
String str = scheme.substring("line=".length());
int idx = str.indexOf(',');
int min, max;
if (idx >= 0) {
min = idx == 0 ? 0 : Integer.parseInt(str.substring(0, idx));
max = idx == str.length() - 1 ? str.length() - 1 : Integer.parseInt(str.substring(idx + 1));
} else {
min = Integer.parseInt(str);
max = min;
}
BufferedReader br = new BufferedReader(new StringReader(sw.toString()));
include = br.lines().skip(min).limit(max - min).collect(Collectors.joining("\n", "", "\n"));
} else {
throw new XMLStreamException("Unsupported text scheme in fragid: " + fragid);
}
if (!integrity.isEmpty()) {
String charset = null;
int idx = integrity.indexOf(',');
if (idx >= 0) {
charset = integrity.substring(idx + 1);
integrity = integrity.substring(0, idx);
if (integrity.startsWith("length=")) {
// TODO: implement
} else if (integrity.startsWith("md5=")) {
// TODO: implement
} else {
throw new XMLStreamException("Unsupported text integrity in fragid: " + fragid);
}
}
}
} else {
include = sw.toString();
}
StreamReaderDelegate sr = new StreamReaderDelegate() {
int state = 0;
@Override
protected XMLStreamReader getDelegate() {
return null;
}
@Override
public int next() throws XMLStreamException {
state++;
return getEventType();
}
@Override
public int getEventType() {
switch (state) {
case 0:
return START_ELEMENT;
case 1:
return CHARACTERS;
}
return END_DOCUMENT;
}
@Override
public String getText() {
return include;
}
@Override
public Location getLocation() {
return XMLStreamLocation2.NOT_AVAILABLE;
}
};
pushContext(input.getSystemId(), sr);
fallback = false;
} catch (IOException e) {
resourceError = e;
}
}
// now skip fallback elements
boolean hasFallback = false;
for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
if (!(child instanceof Element)) {
continue;
}
if (XINCLUDE_NAMESPACE.equals(child.getNamespaceURI())) {
if (XINCLUDE_FALLBACK.equals(child.getLocalName())) {
if (hasFallback) {
throw new XMLStreamException("One one xi:fallback element can be present", startLocation);
}
hasFallback = true;
if (fallback) {
XMLStreamReader sr = factory.createXMLStreamReader(new DOMSource(child));
sr.nextTag(); // the fallback
sr.next(); // next
sr = new FragmentReader(sr);
pushContext(currentLocation, sr);
break;
}
} else {
throw new XMLStreamException(
"Element " + child.getLocalName() + " cannot be present inside the include element",
startLocation);
}
}
}
}