
net.sf.saxon.tree.util.ProcInstParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Saxon-HE Show documentation
Show all versions of Saxon-HE Show documentation
The XSLT and XQuery Processor
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 Saxonica Limited.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package net.sf.saxon.tree.util;
/**
* ProcInstParser is used to parse pseudo-attributes within Processing Instructions
*
* @author Michael H. Kay
* @version 10 July 2000
*/
public class ProcInstParser {
/**
* Class is never instantiated
*/
private ProcInstParser() {
}
/**
* Get a pseudo-attribute. This is useful only if the processing instruction data part
* uses pseudo-attribute syntax, which it does not have to. This syntax is as described
* in the W3C Recommendation "Associating Style Sheets with XML Documents".
*
* @return the value of the pseudo-attribute if present, or null if not
*/
/*@Nullable*/
public static String getPseudoAttribute(/*@NotNull*/ String content, /*@NotNull*/ String name) {
int pos = 0;
while (pos <= content.length() - 4) { // minimum length of x=""
int nextQuote = -1;
for (int q = pos; q < content.length(); q++) {
if (content.charAt(q) == '"' || content.charAt(q) == '\'') {
nextQuote = q;
break;
}
}
if (nextQuote < 0) return null;
int closingQuote = content.indexOf(content.charAt(nextQuote), nextQuote + 1);
if (closingQuote < 0) return null;
int nextName = content.indexOf(name, pos);
if (nextName < 0) return null;
if (nextName < nextQuote) {
// check only spaces and equal signs between the name and the quote
boolean found = true;
for (int s = nextName + name.length(); s < nextQuote; s++) {
char c = content.charAt(s);
if (!Character.isWhitespace(c) && c != '=') {
found = false;
break;
}
}
if (found) {
String val = content.substring(nextQuote + 1, closingQuote);
String u = unescape(val);
if (u == null) {
// unescaping failed
return val;
} else {
return u;
}
}
}
pos = closingQuote + 1;
}
return null;
}
/**
* Interpret character references and built-in entity references.
*
* @return value with character references and built-in entity references expanded.
* If badly-formed or unrecognized references are found, return null
*/
/*@Nullable*/
private static String unescape(/*@NotNull*/ String value) {
if (value.indexOf('&') < 0) return value;
FastStringBuffer sb = new FastStringBuffer(value.length());
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '&') {
if (i + 2 < value.length() && value.charAt(i + 1) == '#') {
if (value.charAt(i + 2) == 'x') {
int x = i + 3;
int charval = 0;
while (x < value.length() && value.charAt(x) != ';') {
int digit = "0123456789abcdef".indexOf(value.charAt(x));
if (digit < 0) {
digit = "0123456789ABCDEF".indexOf(value.charAt(x));
}
if (digit < 0) {
return null;
}
charval = charval * 16 + digit;
x++;
}
char hexchar = (char) charval;
sb.append(hexchar);
i = x;
} else {
int x = i + 2;
int charval = 0;
while (x < value.length() && value.charAt(x) != ';') {
int digit = "0123456789".indexOf(value.charAt(x));
if (digit < 0) {
return null;
}
charval = charval * 10 + digit;
x++;
}
char decchar = (char) charval;
sb.append(decchar);
i = x;
}
} else if (value.substring(i + 1).startsWith("lt;")) {
sb.append('<');
i += 3;
} else if (value.substring(i + 1).startsWith("gt;")) {
sb.append('>');
i += 3;
} else if (value.substring(i + 1).startsWith("amp;")) {
sb.append('&');
i += 4;
} else if (value.substring(i + 1).startsWith("quot;")) {
sb.append('"');
i += 5;
} else if (value.substring(i + 1).startsWith("apos;")) {
sb.append('\'');
i += 5;
} else {
return null;
}
} else {
sb.append(c);
}
}
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy