/*
* sulky-modules - several general-purpose modules.
* Copyright (C) 2007-2014 Joern Huxhorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright 2007-2014 Joern Huxhorn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.huxhorn.sulky.stax;
import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.slf4j.Logger;
public final class StaxUtilities
{
private static final char TAB = 0x09;
private static final char LINE_FEED = 0x0A;
private static final char CARRIAGE_RETURN = 0x0D;
private static final char SPACE = 0x20;
public static final String CDATA_END = "]]>";
public static final String XML_SCHEMA_INSTANCE_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
public static final String XML_SCHEMA_INSTANCE_PREFIX = "xsi";
public static final String XML_SCHEMA_INSTANCE_SCHEMA_LOCATION_ATTRIBUTE = "schemaLocation";
public static final String NO_PREFIX = "";
private static final String NEWLINE = "\n";
private static final String INDENT = "\t";
private StaxUtilities()
{}
/**
* Shortcut for readSimpleTextNodeIfAvailable(reader, namespaceURI, nodeName, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE).
*
* @param reader the reader used to read the text node.
* @param namespaceURI does not check against namespace if null.
* @param nodeName the name of the node to be read.
* @return the read text.
* @throws XMLStreamException if the reader throws an exception.
*/
public static String readSimpleTextNodeIfAvailable(XMLStreamReader reader, String namespaceURI, String nodeName)
throws XMLStreamException
{
return readSimpleTextNodeIfAvailable(reader, namespaceURI, nodeName, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE);
}
/**
* Reads the content of the given text node if available. Otherwise returns null.
*
* @param reader the reader used to read the text node.
* @param namespaceURI does not check against namespace if null.
* @param nodeName the name of the node to be read.
* @param whiteSpace the way whitespace is being handled.
* @return the read text.
* @throws XMLStreamException if the reader throws an exception.
*/
public static String readSimpleTextNodeIfAvailable(XMLStreamReader reader, String namespaceURI, String nodeName, WhiteSpaceHandling whiteSpace)
throws XMLStreamException
{
int type = reader.getEventType();
String result = null;
if(XMLStreamConstants.START_ELEMENT == type && nodeName.equals(reader.getLocalName()))
{
if(namespaceURI == null || namespaceURI.equals(reader.getNamespaceURI()))
{
result = readText(reader, whiteSpace);
reader.nextTag();
}
}
return result;
}
/**
* Shortcut for readText(reader, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE).
*
* @param reader the reader.
* @return the read text.
* @throws XMLStreamException as thrown by reader.
*/
public static String readText(XMLStreamReader reader)
throws XMLStreamException
{
return readText(reader, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE);
}
public static String readText(XMLStreamReader reader, WhiteSpaceHandling whiteSpace)
throws XMLStreamException
{
String result = reader.getElementText();
result = processWhiteSpace(result, whiteSpace);
//reader.nextTag();
return result;
}
public static String processWhiteSpace(String string, WhiteSpaceHandling whiteSpace)
{
if(string == null)
{
return null;
}
switch(whiteSpace)
{
case PRESERVE_NORMALIZE_NEWLINE:
return normalizeNewlines(string);
case REPLACE:
return replaceWhiteSpace(string);
case COLLAPSE:
return collapseWhiteSpace(string);
}
return string;
}
/**
* After the processing implied by replace, contiguous sequences of #x20's are collapsed to a single #x20,
* and leading and trailing #x20's are removed.
*
* @param string the string to be collapsed.
* @return the string with collapsed whitespace, null if string is null.
* @see #replaceWhiteSpace(String)
*/
public static String collapseWhiteSpace(String string)
{
if(string == null)
{
return null;
}
String replaced = replaceWhiteSpace(string);
char[] chars = replaced.toCharArray();
StringBuilder result = new StringBuilder(replaced.length());
boolean needSpace = false;
for(char c : chars)
{
if(c == SPACE)
{
if(result.length() != 0)
{
// we are not at the start anymore
needSpace = true;
}
}
else
{
if(needSpace)
{
needSpace = false;
result.append(SPACE);
}
result.append(c);
}
}
return result.toString();
}
/**
* All occurrences of #x9 (tab), #xA (line feed) and #xD (carriage return) are replaced with #x20 (space)
*
* @param string th input.
* @return the string with replaced whitespace, null if string is null.
*/
public static String replaceWhiteSpace(String string)
{
if(string == null)
{
return null;
}
StringBuilder result = new StringBuilder(string);
for(int i = 0; i < result.length(); i++)
{
char c = result.charAt(i);
if(c == TAB || c == CARRIAGE_RETURN || c == LINE_FEED)
{
result.setCharAt(i, SPACE);
}
}
return result.toString();
}
/**
* Shortcut for readAttributeValue(reader, namespaceURI, name, WhiteSpaceHandling.COLLAPSE);
*
* @param reader the reader
* @param namespaceURI the namespaceURI
* @param name the name
* @return the result of readAttributeValue(reader, namespaceURI, name, WhiteSpaceHandling.COLLAPSE);
*/
public static String readAttributeValue(XMLStreamReader reader, String namespaceURI, String name)
{
return readAttributeValue(reader, namespaceURI, name, WhiteSpaceHandling.COLLAPSE);
}
public static String readAttributeValue(XMLStreamReader reader, String namespaceURI, String name, WhiteSpaceHandling whiteSpace)
{
String attributeValue = reader.getAttributeValue(namespaceURI, name);
if(attributeValue == null)
{
// this actually seems to be okay... attributes are unique
attributeValue = reader.getAttributeValue(null, name);
}
return processWhiteSpace(attributeValue, whiteSpace);
}
public static void writeNamespace(XMLStreamWriter writer, String prefix, String namespaceURI)
throws XMLStreamException
{
if(prefix == null || NO_PREFIX.equals(prefix))
{
writer.writeDefaultNamespace(namespaceURI);
}
else
{
writer.writeNamespace(prefix, namespaceURI);
}
}
public static NamespaceInfo setNamespace(XMLStreamWriter writer, String prefix, String namespaceURI, String defaultPrefix)
throws XMLStreamException
{
String p = writer.getPrefix(namespaceURI);
if(p == null)
{
// not defined yet
NamespaceContext nsc = writer.getNamespaceContext();
if(prefix == null || NO_PREFIX.equals(prefix))
{
String defaultNamespaceURI = nsc.getNamespaceURI(NO_PREFIX);
if(defaultNamespaceURI == null || XMLConstants.NULL_NS_URI.equals(defaultNamespaceURI))
{
// no defaultNS yet.
writer.setDefaultNamespace(namespaceURI);
return new NamespaceInfo(null, true);
}
return resolveNamespacePrefix(writer, nsc, defaultPrefix, namespaceURI);
}
else
{
return resolveNamespacePrefix(writer, nsc, prefix, namespaceURI);
}
}
else
{
if(NO_PREFIX.equals(p))
{
p = null;
}
return new NamespaceInfo(p, false);
}
}
private static NamespaceInfo resolveNamespacePrefix(XMLStreamWriter writer, NamespaceContext nsc, String prefix, String namespaceURI)
throws XMLStreamException
{
int counter = 1;
String prefixCandidate = prefix;
for(;;)
{
String ns = nsc.getNamespaceURI(prefixCandidate);
if(!XMLConstants.NULL_NS_URI.equals(ns))
{
writer.setPrefix(prefixCandidate, namespaceURI);
return new NamespaceInfo(prefixCandidate, true);
}
counter++;
prefixCandidate = prefix + counter;
}
}
public static class NamespaceInfo
{
private String prefix;
private boolean created;
public NamespaceInfo(String prefix, boolean created)
{
this.prefix = prefix;
this.created = created;
}
public String getPrefix()
{
return prefix;
}
public boolean isCreated()
{
return created;
}
}
/**
* If namespaceURI is null, this method calls writer.writeStartElement without namespaceURI argument.
* Otherwise the one including it is being used.
*
* @param writer the writer.
* @param prefix the prefix.
* @param namespaceURI the namespaceURI.
* @param nodeName the node name.
* @throws XMLStreamException exceptions as thrown by the writer.
*/
public static void writeStartElement(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName)
throws XMLStreamException
{
if(namespaceURI != null)
{
if(prefix != null && !NO_PREFIX.equals(prefix))
{
writer.writeStartElement(prefix, nodeName, namespaceURI);
}
else
{
writer.writeStartElement(namespaceURI, nodeName);
}
}
else
{
writer.writeStartElement(nodeName);
}
}
public static void writeEmptyElement(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName)
throws XMLStreamException
{
if(namespaceURI != null)
{
if(prefix != null && !NO_PREFIX.equals(prefix))
{
writer.writeEmptyElement(prefix, nodeName, namespaceURI);
}
else
{
writer.writeEmptyElement(namespaceURI, nodeName);
}
}
else
{
writer.writeEmptyElement(nodeName);
}
}
/**
* Shortcut for writeAttribute(writer, prefix, namespaceURI, name, value, WhiteSpaceHandling.COLLAPSE).
*
* @param writer the writer.
* @param qualified whether or not attribute should be prefixed.
* @param prefix the prefix.
* @param namespaceURI the namespaceURI.
* @param name the name.
* @param value the value.
* @throws XMLStreamException as thrown by writer.
*/
public static void writeAttribute(XMLStreamWriter writer, boolean qualified, String prefix, String namespaceURI, String name, String value)
throws XMLStreamException
{
writeAttribute(writer, qualified, prefix, namespaceURI, name, value, WhiteSpaceHandling.COLLAPSE);
}
public static void writeAttribute(XMLStreamWriter writer, boolean qualified, String prefix, String namespaceURI, String name, String value, WhiteSpaceHandling whiteSpace)
throws XMLStreamException
{
value = processWhiteSpace(value, whiteSpace);
if(qualified && namespaceURI != null)
{
if(prefix == null || NO_PREFIX.equals(prefix))
{
writer.writeAttribute(namespaceURI, name, value);
}
else
{
writer.writeAttribute(prefix, namespaceURI, name, value);
}
}
else
{
writer.writeAttribute(name, value);
}
}
/**
* Shortcut for writeAttributeIfNotNull(writer, prefix, namespaceURI, name, value, WhiteSpaceHandling.COLLAPSE).
*
* @param writer the writer.
* @param qualified whether or not attribute should be prefixed.
* @param prefix the prefix.
* @param namespaceURI the namespaceURI.
* @param name the name.
* @param value the value.
* @throws XMLStreamException as thrown by writer.
*/
public static void writeAttributeIfNotNull(XMLStreamWriter writer, boolean qualified, String prefix, String namespaceURI, String name, String value)
throws XMLStreamException
{
writeAttributeIfNotNull(writer, qualified, prefix, namespaceURI, name, value, WhiteSpaceHandling.COLLAPSE);
}
public static void writeAttributeIfNotNull(XMLStreamWriter writer, boolean qualified, String prefix, String namespaceURI, String name, String value, WhiteSpaceHandling whiteSpace)
throws XMLStreamException
{
if(value != null)
{
writeAttribute(writer, qualified, prefix, namespaceURI, name, value, whiteSpace);
}
}
/**
* Normalizes the newlines of the string.
*
* Replaces "\r\n", "\n\r" and "\r" with a single "\n".
*
* @param input the input.
* @return a string with cleaned up newlines, i.e. only \n, no \r.
*/
public static String normalizeNewlines(String input)
{
String result = input;
if(input != null)
{
char[] chars = input.toCharArray();
final int length = chars.length;
int startWritePos = 0;
StringBuilder resultBuffer = null;
char previousChar = 0;
for(int index = 0; index < length; index++)
{
char ch = chars[index];
switch(ch)
{
case '\r':
if(resultBuffer == null)
{
resultBuffer = new StringBuilder();
}
resultBuffer.append(chars, startWritePos, index - startWritePos);
if(previousChar != '\n')
{
resultBuffer.append(NEWLINE);
previousChar = ch;
}
else
{
// reset so only pairs are ignored
previousChar = 0;
}
startWritePos = index + 1;
break;
case '\n':
if(resultBuffer == null)
{
resultBuffer = new StringBuilder();
}
resultBuffer.append(chars, startWritePos, index - startWritePos);
if(previousChar != '\r')
{
resultBuffer.append(NEWLINE);
previousChar = ch;
}
else
{
// reset so only pairs are ignored
previousChar = 0;
}
startWritePos = index + 1;
break;
default:
previousChar = 0;
break;
}
}
// Write any pending data
if(resultBuffer != null)
{
resultBuffer.append(chars, startWritePos, length - startWritePos);
result = resultBuffer.toString();
}
}
return result;
}
/**
* Writes a <nodeName> node containing the given text.
*
* If tryUsingCData is true and the text does not contain the CData end token,
* the text will be written using writeCData. Otherwise writeCharacters is used.
*
* @param writer the writer.
* @param prefix the prefix of the node. May be null.
* @param namespaceURI the namespaceURI of the node. May be null.
* @param nodeName the nodeName of the node.
* @param text the text that is written into to node. Must not be null.
* @param whiteSpace the desired WhiteSpaceHandling.
* @param tryUsingCData is trying to is CData instead of encoded characters if possible.
* @throws XMLStreamException as thrown by writer.
* @see #writeText(javax.xml.stream.XMLStreamWriter, String, WhiteSpaceHandling, boolean)
*/
public static void writeSimpleTextNode(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName, String text, WhiteSpaceHandling whiteSpace, boolean tryUsingCData)
throws XMLStreamException
{
writeStartElement(writer, prefix, namespaceURI, nodeName);
writeText(writer, text, whiteSpace, tryUsingCData);
writer.writeEndElement();
}
/**
* Shortcut for writeSimpleTextNode(writer, prefix, namespaceURI, nodeName, text, false).
*
* It won't try to use CDATA.
*
* @param writer the writer.
* @param prefix the prefix of the node. May be null.
* @param namespaceURI the namespaceURI of the node. May be null.
* @param nodeName the nodeName of the node.
* @param text the text that is written into to node. Must not be null.
* @param whiteSpace the desired WhiteSpaceHandling.
* @throws XMLStreamException as thrown by writer.
* @see #writeSimpleTextNode(javax.xml.stream.XMLStreamWriter, String, String, String, String, WhiteSpaceHandling, boolean)
*/
public static void writeSimpleTextNode(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName, String text, WhiteSpaceHandling whiteSpace)
throws XMLStreamException
{
writeSimpleTextNode(writer, prefix, namespaceURI, nodeName, text, whiteSpace, false);
}
/**
* Shortcut for writeSimpleTextNode(writer, prefix, namespaceURI, nodeName, text, false).
*
* It won't try to use CDATA and uses WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE.
*
* @param writer the writer.
* @param prefix the prefix of the node. May be null.
* @param namespaceURI the namespaceURI of the node. May be null.
* @param nodeName the nodeName of the node.
* @param text the text that is written into to node. Must not be null.
* @throws XMLStreamException as thrown by writer.
* @see #writeSimpleTextNode(javax.xml.stream.XMLStreamWriter, String, String, String, String, WhiteSpaceHandling, boolean)
*/
public static void writeSimpleTextNode(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName, String text)
throws XMLStreamException
{
writeSimpleTextNode(writer, prefix, namespaceURI, nodeName, text, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE, false);
}
/**
* Writes a <nodeName> node containing the given text if text is not null.
*
* If tryUsingCData is true and the text does not contain the CData end token,
* the text will be written using writeCData. Otherwise writeCharacters is used.
*
* @param writer the writer.
* @param prefix the prefix of the node. May be null.
* @param namespaceURI the namespaceURI of the node. May be null.
* @param nodeName the nodeName of the node.
* @param text the text that is written into to node. May be null.
* @param whiteSpace the desired WhiteSpaceHandling.
* @param tryUsingCData is trying to is CData instead of encoded characters if possible.
* @throws XMLStreamException as thrown by writer.
* @see #writeSimpleTextNode(javax.xml.stream.XMLStreamWriter, String, String, String, String, WhiteSpaceHandling, boolean)
*/
public static void writeSimpleTextNodeIfNotNull(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName, String text, WhiteSpaceHandling whiteSpace, boolean tryUsingCData)
throws XMLStreamException
{
if(text != null)
{
writeSimpleTextNode(writer, prefix, namespaceURI, nodeName, text, whiteSpace, tryUsingCData);
}
}
/**
* Writes a <nodeName> node containing the given text if text is not null.
*
* It won't try to use CDATA.
*
* @param writer the writer.
* @param prefix the prefix of the node. May be null.
* @param namespaceURI the namespaceURI of the node. May be null.
* @param nodeName the nodeName of the node.
* @param text the text that is written into to node. May be null.
* @param whiteSpace the desired WhiteSpaceHandling.
* @throws XMLStreamException as thrown by writer.
* @see #writeSimpleTextNode(javax.xml.stream.XMLStreamWriter, String, String, String, String, WhiteSpaceHandling, boolean)
*/
public static void writeSimpleTextNodeIfNotNull(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName, String text, WhiteSpaceHandling whiteSpace)
throws XMLStreamException
{
if(text != null)
{
writeSimpleTextNode(writer, prefix, namespaceURI, nodeName, text, whiteSpace, false);
}
}
/**
* Writes a <nodeName> node containing the given text if text is not null.
*
* It won't try to use CDATA and uses WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE.
*
* @param writer the writer.
* @param prefix the prefix of the node. May be null.
* @param namespaceURI the namespaceURI of the node. May be null.
* @param nodeName the nodeName of the node.
* @param text the text that is written into to node. May be null.
* @throws XMLStreamException as thrown by writer.
* @see #writeSimpleTextNode(javax.xml.stream.XMLStreamWriter, String, String, String, String, WhiteSpaceHandling, boolean)
*/
public static void writeSimpleTextNodeIfNotNull(XMLStreamWriter writer, String prefix, String namespaceURI, String nodeName, String text)
throws XMLStreamException
{
if(text != null)
{
writeSimpleTextNode(writer, prefix, namespaceURI, nodeName, text, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE, false);
}
}
/**
* Writes either characters or CDATA.
*
* CDATA is only used if tryUsingCData is true and text does not contain the CDATA end token.
*
* @param writer the writer.
* @param text the text to be written. Must not be null.
* @param whiteSpace the desired WhiteSpaceHandling.
* @param tryUsingCData try using CDATA, if possible.
* @throws XMLStreamException as thrown by writer.
*/
public static void writeText(XMLStreamWriter writer, String text, WhiteSpaceHandling whiteSpace, boolean tryUsingCData)
throws XMLStreamException
{
processWhiteSpace(text, whiteSpace);
if(tryUsingCData && !text.contains(CDATA_END))
{
writer.writeCData(text);
}
else
{
writer.writeCharacters(text);
}
}
/**
* Shortcut for writeText(writer, text, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE, false).
*
* @param writer the writer.
* @param text the text.
* @throws XMLStreamException as thrown by writer.
*/
public static void writeText(XMLStreamWriter writer, String text)
throws XMLStreamException
{
writeText(writer, text, WhiteSpaceHandling.PRESERVE_NORMALIZE_NEWLINE, false);
}
public static String getEventTypeString(int eventType)
{
switch(eventType)
{
case XMLStreamConstants.ATTRIBUTE:
return "ATTRIBUTE";
case XMLStreamConstants.CDATA:
return "CDATA";
case XMLStreamConstants.CHARACTERS:
return "CHARACTERS";
case XMLStreamConstants.COMMENT:
return "COMMENT";
case XMLStreamConstants.DTD:
return "DTD";
case XMLStreamConstants.END_DOCUMENT:
return "END_DOCUMENT";
case XMLStreamConstants.END_ELEMENT:
return "END_ELEMENT";
case XMLStreamConstants.ENTITY_DECLARATION:
return "ENTITY_DECLARATION";
case XMLStreamConstants.ENTITY_REFERENCE:
return "ENTITY_REFERENCE";
case XMLStreamConstants.NAMESPACE:
return "NAMESPACE";
case XMLStreamConstants.NOTATION_DECLARATION:
return "NOTATION_DECLARATION";
case XMLStreamConstants.PROCESSING_INSTRUCTION:
return "PROCESSING_INSTRUCTION";
case XMLStreamConstants.SPACE:
return "SPACE";
case XMLStreamConstants.START_DOCUMENT:
return "START_DOCUMENT";
case XMLStreamConstants.START_ELEMENT:
return "START_ELEMENT";
default:
return "<unknown type!>";
}
}
public static String writerStatus(String msg, XMLStreamWriter writer, String namespaceURI)
{
StringBuilder msgBuf = new StringBuilder();
NamespaceContext nsc = writer.getNamespaceContext();
Iterator iter = nsc.getPrefixes(namespaceURI);
if(msg != null)
{
msgBuf.append(msg).append(" - ");
}
msgBuf.append("Prefixes defined for namespace ").append(namespaceURI).append(":");
if(iter.hasNext())
{
boolean isFirst = true;
while(iter.hasNext())
{
if(!isFirst)
{
msgBuf.append(", ");
}
else
{
isFirst = false;
}
msgBuf.append("'").append(iter.next()).append("'");
}
}
else
{
msgBuf.append("Undefined.");
}
return msgBuf.toString();
}
public static void logWriter(Logger logger, String msg, XMLStreamWriter writer, String namespaceURI)
{
if(logger.isDebugEnabled())
{
logger.debug(writerStatus(msg, writer, namespaceURI));
}
}
public static String readerStatus(String msg, XMLStreamReader reader)
{
int type = reader.getEventType();
StringBuilder msgBuf = new StringBuilder(msg);
msgBuf.append(NEWLINE);
msgBuf.append(INDENT).append("eventType=").append(getEventTypeString(type)).append(NEWLINE);
if(type == XMLStreamConstants.START_ELEMENT || type == XMLStreamConstants.END_ELEMENT)
{
msgBuf.append(INDENT).append("localName=").append(reader.getLocalName()).append(NEWLINE);
msgBuf.append(INDENT).append("namespaceURI=").append(reader.getNamespaceURI()).append(NEWLINE);
}
if(type == XMLStreamConstants.START_ELEMENT)
{
int attCount = reader.getAttributeCount();
msgBuf.append(INDENT).append("attributeCount=").append(attCount).append(NEWLINE);
for(int i = 0; i < attCount; i++)
{
msgBuf.append(INDENT).append(INDENT).append("#####\n");
msgBuf.append(INDENT).append(INDENT).append("attributeNamespace=").append(reader.getAttributeNamespace(i))
.append(NEWLINE);
msgBuf.append(INDENT).append(INDENT).append("attributeLocalName=").append(reader.getAttributeLocalName(i))
.append(NEWLINE);
msgBuf.append(INDENT).append(INDENT).append("attributeValue=").append(reader.getAttributeValue(i)).append(NEWLINE);
msgBuf.append(INDENT).append(INDENT).append("attributePrefix=").append(reader.getAttributePrefix(i)).append(NEWLINE);
}
}
msgBuf.append(INDENT).append("readerClass: ").append(reader.getClass().getName());
return msgBuf.toString();
}
public static void logReader(Logger logger, String msg, XMLStreamReader reader)
{
if(logger.isDebugEnabled())
{
logger.debug(readerStatus(msg, reader));
}
}
}