001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019 020package org.apache.wiki.util; 021 022import org.apache.commons.lang3.StringUtils; 023import org.apache.log4j.Logger; 024import org.jdom2.Document; 025import org.jdom2.Element; 026import org.jdom2.JDOMException; 027import org.jdom2.filter.Filters; 028import org.jdom2.input.SAXBuilder; 029import org.jdom2.xpath.XPathExpression; 030import org.jdom2.xpath.XPathFactory; 031 032import java.io.IOException; 033import java.io.InputStream; 034import java.net.URL; 035import java.util.ArrayList; 036import java.util.Collections; 037import java.util.Enumeration; 038import java.util.HashSet; 039import java.util.List; 040import java.util.Set; 041 042/** 043 * Utility class to parse XML files. 044 * <p> 045 * This uses JDOM2 as its backing implementation. 046 * </p> 047 * 048 * @since 2.10 049 */ 050public final class XmlUtil { 051 052 private static final Logger log = Logger.getLogger( XmlUtil.class ); 053 private XmlUtil() {} 054 055 /** 056 * Parses the given XML file and returns the requested nodes. If there's an error accessing or parsing the file, an 057 * empty list is returned. 058 * 059 * @param xml file to parse; matches all resources from classpath, filters repeated items. 060 * @param requestedNodes requestd nodes on the xml file 061 * @return the requested nodes of the XML file. 062 */ 063 public static List<Element> parse( String xml, String requestedNodes ) 064 { 065 if( StringUtils.isNotEmpty( xml ) && StringUtils.isNotEmpty( requestedNodes ) ) { 066 Set<Element> readed = new HashSet<Element>(); 067 SAXBuilder builder = new SAXBuilder(); 068 try { 069 Enumeration< URL > resources = XmlUtil.class.getClassLoader().getResources( xml ); 070 while( resources.hasMoreElements() ) { 071 URL resource = resources.nextElement(); 072 log.debug( "reading " + resource.toString() ); 073 Document doc = builder.build( resource ); 074 XPathFactory xpfac = XPathFactory.instance(); 075 XPathExpression<Element> xp = xpfac.compile( requestedNodes, Filters.element() ); 076 readed.addAll( xp.evaluate( doc ) ); // filter out repeated items 077 } 078 return new ArrayList<Element>( readed ); 079 } catch ( IOException ioe ) { 080 log.error( "Couldn't load all " + xml + " resources", ioe ); 081 } catch ( JDOMException jdome ) { 082 log.error( "error parsing " + xml + " resources", jdome ); 083 } 084 } 085 return Collections.emptyList(); 086 } 087 088 /** 089 * Parses the given stream and returns the requested nodes. If there's an error accessing or parsing the stream, an 090 * empty list is returned. 091 * 092 * @param xmlStream stream to parse. 093 * @param requestedNodes requestd nodes on the xml stream. 094 * @return the requested nodes of the XML stream. 095 */ 096 public static List< Element > parse( InputStream xmlStream, String requestedNodes ) { 097 if( xmlStream != null && StringUtils.isNotEmpty( requestedNodes ) ) { 098 SAXBuilder builder = new SAXBuilder(); 099 try { 100 Document doc = builder.build( xmlStream ); 101 XPathFactory xpfac = XPathFactory.instance(); 102 XPathExpression< Element > xp = xpfac.compile( requestedNodes,Filters.element() ); 103 return xp.evaluate( doc ); 104 } catch ( IOException ioe ) { 105 log.error( "Couldn't load all " + xmlStream + " resources", ioe ); 106 } catch ( JDOMException jdome ) { 107 log.error( "error parsing " + xmlStream + " resources", jdome ); 108 } 109 } 110 return Collections.emptyList(); 111 } 112 113}