📄 cmsxmlutils.java
字号:
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding(encoding);
format.setSuppressDeclaration(true);
XMLWriter writer = new XMLWriter(out, format);
writer.setEscapeText(false);
writer.write(node);
writer.close();
} catch (Exception e) {
throw new CmsXmlException(Messages.get().container(Messages.ERR_MARSHALLING_XML_DOC_0), e);
}
return new String(out.toByteArray());
}
/**
* Removes the first Xpath element from the path.<p>
*
* If the provided path does not contain a "/" character,
* it is returned unchanged.<p>
*
* <p>Examples:<br>
* <code>title</code> is left untouched<br>
* <code>title[1]</code> is left untouched<br>
* <code>title/subtitle</code> becomes <code>subtitle</code><br>
* <code>title[1]/subtitle[1]</code> becomes <code>subtitle[1]</code><p>
*
* @param path the Xpath to remove the first element from
*
* @return the path with the first element removed
*/
public static String removeFirstXpathElement(String path) {
int pos = path.indexOf('/');
if (pos < 0) {
return path;
}
return path.substring(pos + 1);
}
/**
* Removes the last Xpath element from the path.<p>
*
* If the provided path does not contain a "/" character,
* it is returned unchanged.<p>
*
* <p>Examples:<br>
* <code>title</code> is left untouched<br>
* <code>title[1]</code> is left untouched<br>
* <code>title/subtitle</code> becomes <code>title</code><br>
* <code>title[1]/subtitle[1]</code> becomes <code>title[1]</code><p>
*
* @param path the Xpath to remove the last element from
*
* @return the path with the last element removed
*/
public static String removeLastXpathElement(String path) {
int pos = path.lastIndexOf('/');
if (pos < 0) {
return path;
}
return path.substring(0, pos);
}
/**
* Removes the last complex Xpath element from the path.<p>
*
* The same as {@link #removeLastXpathElement(String)} both it works with more complex xpaths.
*
* <p>Example:<br>
* <code>system/backup[@date='23/10/2003']/resource[path='/a/b/c']</code> becomes <code>system/backup[@date='23/10/2003']</code><p>
*
* @param path the Xpath to remove the last element from
*
* @return the path with the last element removed
*/
public static String removeLastComplexXpathElement(String path) {
int pos = path.lastIndexOf('/');
if (pos < 0) {
return path;
}
// count ' chars
int p = pos;
int count = -1;
while (p > 0) {
count++;
p = path.indexOf("\'", p + 1);
}
String parentPath = path.substring(0, pos);
if (count % 2 == 0) {
// if substring is complete
return parentPath;
}
// if not complete
p = parentPath.lastIndexOf("'");
if (p >= 0) {
// complete it if possible
return removeLastComplexXpathElement(parentPath.substring(0, p));
}
return parentPath;
}
/**
* Removes all Xpath index information from the given input path.<p>
*
* Examples:<br>
* <code>title</code> is left untouched<br>
* <code>title[1]</code> becomes <code>title</code><br>
* <code>title/subtitle</code> is left untouched<br>
* <code>title/subtitle[1]</code> becomes <code>title/subtitle</code><p>
*
* @param path the path to remove the Xpath index information from
*
* @return the simplified Xpath for the given name
*/
public static String removeXpath(String path) {
if (path.indexOf('/') > -1) {
// this is a complex path over more then 1 node
StringBuffer result = new StringBuffer(path.length() + 32);
// split the path into subelements
List elements = CmsStringUtil.splitAsList(path, '/');
int end = elements.size() - 1;
for (int i = 0; i <= end; i++) {
// append [i] to path element if required
result.append(removeXpathIndex((String)elements.get(i)));
if (i < end) {
// append path delimiter if not final path element
result.append('/');
}
}
return result.toString();
}
// this path has only 1 node, remove last index if required
return removeXpathIndex(path);
}
/**
* Removes the last Xpath index from the given path.<p>
*
* Examples:<br>
* <code>title</code> is left untouched<br>
* <code>title[1]</code> becomes <code>title</code><br>
* <code>title/subtitle</code> is left untouched<br>
* <code>title[1]/subtitle[1]</code> becomes <code>title[1]/subtitle</code><p>
*
* @param path the path to remove the Xpath index from
*
* @return the path with the last Xpath index removed
*/
public static String removeXpathIndex(String path) {
int pos1 = path.lastIndexOf('/');
int pos2 = path.lastIndexOf('[');
if ((pos2 < 0) || (pos1 > pos2)) {
return path;
}
return path.substring(0, pos2);
}
/**
* Simplifies an Xpath by removing a leading and a trailing slash from the given path.<p>
*
* Examples:<br>
* <code>title/</code> becomes <code>title</code><br>
* <code>/title[1]/</code> becomes <code>title[1]</code><br>
* <code>/title/subtitle/</code> becomes <code>title/subtitle</code><br>
* <code>/title/subtitle[1]/</code> becomes <code>title/subtitle[1]</code><p>
*
* @param path the path to process
* @return the input with a leading and a trailing slash removed
*/
public static String simplifyXpath(String path) {
StringBuffer result = new StringBuffer(path);
if (result.charAt(0) == '/') {
result.deleteCharAt(0);
}
int pos = result.length() - 1;
if (result.charAt(pos) == '/') {
result.deleteCharAt(pos);
}
return result.toString();
}
/**
* Helper to unmarshal (read) xml contents from a byte array into a document.<p>
*
* Using this method ensures that the OpenCms XML entitiy resolver is used.<p>
*
* @param xmlData the XML data in a byte array
* @param resolver the XML entitiy resolver to use
* @return the base object initialized with the unmarshalled XML document
* @throws CmsXmlException if something goes wrong
* @see CmsXmlUtils#unmarshalHelper(InputSource, EntityResolver)
*/
public static Document unmarshalHelper(byte[] xmlData, EntityResolver resolver) throws CmsXmlException {
return CmsXmlUtils.unmarshalHelper(new InputSource(new ByteArrayInputStream(xmlData)), resolver);
}
/**
* Helper to unmarshal (read) xml contents from an input source into a document.<p>
*
* Using this method ensures that the OpenCms XML entitiy resolver is used.<p>
*
* Important: The encoding provided will NOT be used uring unmarshalling,
* the XML parser will do this on the base of the information in the source String.
* The encoding is used for initializing the created instance of the document,
* which means it will be used when marshalling the document again later.<p>
*
* @param source the XML input source to use
* @param resolver the XML entitiy resolver to use
* @return the unmarshalled XML document
* @throws CmsXmlException if something goes wrong
*/
public static Document unmarshalHelper(InputSource source, EntityResolver resolver) throws CmsXmlException {
try {
SAXReader reader = new SAXReader();
if (resolver != null) {
reader.setEntityResolver(resolver);
}
reader.setMergeAdjacentText(true);
reader.setStripWhitespaceText(true);
return reader.read(source);
} catch (DocumentException e) {
throw new CmsXmlException(Messages.get().container(Messages.ERR_UNMARSHALLING_XML_DOC_0), e);
}
}
/**
* Helper to unmarshal (read) xml contents from a String into a document.<p>
*
* Using this method ensures that the OpenCms XML entitiy resolver is used.<p>
*
* @param xmlData the xml data in a String
* @param resolver the XML entitiy resolver to use
* @return the base object initialized with the unmarshalled XML document
* @throws CmsXmlException if something goes wrong
* @see CmsXmlUtils#unmarshalHelper(InputSource, EntityResolver)
*/
public static Document unmarshalHelper(String xmlData, EntityResolver resolver) throws CmsXmlException {
return CmsXmlUtils.unmarshalHelper(new InputSource(new StringReader(xmlData)), resolver);
}
/**
* Validates the structure of a XML document contained in a byte array
* with the DTD or XML schema used by the document.<p>
*
* @param xmlData a byte array containing a XML document that should be validated
* @param resolver the XML entitiy resolver to use
*
* @throws CmsXmlException if the validation fails
*/
public static void validateXmlStructure(byte[] xmlData, EntityResolver resolver) throws CmsXmlException {
XMLReader reader;
try {
reader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
} catch (SAXException e) {
// xerces parser not available - no schema validation possible
if (LOG.isWarnEnabled()) {
LOG.warn(Messages.get().getBundle().key(Messages.LOG_VALIDATION_INIT_XERXES_SAX_READER_FAILED_0), e);
}
// no validation of the content is possible
return;
}
// turn on validation
try {
reader.setFeature("http://xml.org/sax/features/validation", true);
// turn on schema validation
reader.setFeature("http://apache.org/xml/features/validation/schema", true);
// configure namespace support
reader.setFeature("http://xml.org/sax/features/namespaces", true);
reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
} catch (SAXNotRecognizedException e) {
// should not happen as Xerces 2 support this feature
if (LOG.isWarnEnabled()) {
LOG.warn(Messages.get().getBundle().key(Messages.LOG_SAX_READER_FEATURE_NOT_RECOGNIZED_0), e);
}
// no validation of the content is possible
return;
} catch (SAXNotSupportedException e) {
// should not happen as Xerces 2 support this feature
if (LOG.isWarnEnabled()) {
LOG.warn(Messages.get().getBundle().key(Messages.LOG_SAX_READER_FEATURE_NOT_SUPPORTED_0), e);
}
// no validation of the content is possible
return;
}
// add an error handler which turns any errors into XML
CmsXmlValidationErrorHandler errorHandler = new CmsXmlValidationErrorHandler();
reader.setErrorHandler(errorHandler);
if (resolver != null) {
// set the resolver for the "opencms://" URIs
reader.setEntityResolver(resolver);
}
try {
reader.parse(new InputSource(new ByteArrayInputStream(xmlData)));
} catch (IOException e) {
// should not happen since we read form a byte array
if (LOG.isErrorEnabled()) {
LOG.error(Messages.get().getBundle().key(Messages.LOG_READ_XML_FROM_BYTE_ARR_FAILED_0), e);
}
return;
} catch (SAXException e) {
// should not happen since all errors are handled in the XML error handler
if (LOG.isErrorEnabled()) {
LOG.error(Messages.get().getBundle().key(Messages.LOG_PARSE_SAX_EXC_0), e);
}
return;
}
if (errorHandler.getErrors().elements().size() > 0) {
// there was at last one validation error, so throw an exception
StringWriter out = new StringWriter(256);
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(out, format);
try {
writer.write(errorHandler.getErrors());
writer.write(errorHandler.getWarnings());
writer.close();
} catch (IOException e) {
// should not happen since we write to a StringWriter
if (LOG.isErrorEnabled()) {
LOG.error(Messages.get().getBundle().key(Messages.LOG_STRINGWRITER_IO_EXC_0), e);
}
}
// generate String from XML for display of document in error message
throw new CmsXmlException(Messages.get().container(Messages.ERR_XML_VALIDATION_1, out.toString()));
}
}
/**
* Validates the structure of a XML document with the DTD or XML schema used
* by the document.<p>
*
* @param document a XML document that should be validated
* @param encoding the encoding to use when marshalling the XML document (required)
* @param resolver the XML entitiy resolver to use
*
* @throws CmsXmlException if the validation fails
*/
public static void validateXmlStructure(Document document, String encoding, EntityResolver resolver)
throws CmsXmlException {
// generate bytes from document
byte[] xmlData = ((ByteArrayOutputStream)marshal(document, new ByteArrayOutputStream(512), encoding)).toByteArray();
validateXmlStructure(xmlData, resolver);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -