/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/* $Id: XMLUtil.java 1805173 2017-08-16 10:50:04Z ssteiner $ */

package org.apache.fop.util;

import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

A collection of utility method for XML handling.
/** * A collection of utility method for XML handling. */
public final class XMLUtil implements XMLConstants { private XMLUtil() { }
Returns an attribute value as a boolean value.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
  • defaultValue – the default value if the attribute is not specified
Returns:the attribute value as a boolean
/** * Returns an attribute value as a boolean value. * @param attributes the Attributes object * @param name the name of the attribute * @param defaultValue the default value if the attribute is not specified * @return the attribute value as a boolean */
public static boolean getAttributeAsBoolean(Attributes attributes, String name, boolean defaultValue) { String s = attributes.getValue(name); if (s == null) { return defaultValue; } else { return Boolean.valueOf(s); } }
Returns an attribute value as a int value.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
  • defaultValue – the default value if the attribute is not specified
Returns:the attribute value as an int
/** * Returns an attribute value as a int value. * @param attributes the Attributes object * @param name the name of the attribute * @param defaultValue the default value if the attribute is not specified * @return the attribute value as an int */
public static int getAttributeAsInt(Attributes attributes, String name, int defaultValue) { String s = attributes.getValue(name); if (s == null) { return defaultValue; } else { return Integer.parseInt(s); } }
Returns an attribute value as a int value.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
Throws:
Returns:the attribute value as an int
/** * Returns an attribute value as a int value. * @param attributes the Attributes object * @param name the name of the attribute * @return the attribute value as an int * @throws SAXException if the attribute is missing */
public static int getAttributeAsInt(Attributes attributes, String name) throws SAXException { String s = attributes.getValue(name); if (s == null) { throw new SAXException("Attribute '" + name + "' is missing"); } else { return Integer.parseInt(s); } }
Returns an attribute value as a Integer value.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
Returns:the attribute value as an Integer or null if the attribute is missing
/** * Returns an attribute value as a Integer value. * @param attributes the Attributes object * @param name the name of the attribute * @return the attribute value as an Integer or null if the attribute is missing */
public static Integer getAttributeAsInteger(Attributes attributes, String name) { String s = attributes.getValue(name); if (s == null) { return null; } else { return Integer.valueOf(s); } }
Returns an attribute value as a Rectangle2D value. The string value is expected as 4 double-precision numbers separated by whitespace.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
Returns:the attribute value as an Rectangle2D
/** * Returns an attribute value as a Rectangle2D value. The string value is expected as 4 * double-precision numbers separated by whitespace. * @param attributes the Attributes object * @param name the name of the attribute * @return the attribute value as an Rectangle2D */
public static Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) { String s = attributes.getValue(name).trim(); double[] values = ConversionUtils.toDoubleArray(s, "\\s"); if (values.length != 4) { throw new IllegalArgumentException("Rectangle must consist of 4 double values!"); } return new Rectangle2D.Double(values[0], values[1], values[2], values[3]); }
Returns an attribute value as a Rectangle value. The string value is expected as 4 integer numbers separated by whitespace.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
Returns:the attribute value as an Rectangle
/** * Returns an attribute value as a Rectangle value. The string value is expected as 4 * integer numbers separated by whitespace. * @param attributes the Attributes object * @param name the name of the attribute * @return the attribute value as an Rectangle */
public static Rectangle getAttributeAsRectangle(Attributes attributes, String name) { String s = attributes.getValue(name); if (s == null) { return null; } int[] values = ConversionUtils.toIntArray(s.trim(), "\\s"); if (values.length != 4) { throw new IllegalArgumentException("Rectangle must consist of 4 int values!"); } return new Rectangle(values[0], values[1], values[2], values[3]); }
Returns an attribute value as a integer array. The string value is expected as 4 integer numbers separated by whitespace.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
Returns:the attribute value as an int array
/** * Returns an attribute value as a integer array. The string value is expected as 4 * integer numbers separated by whitespace. * @param attributes the Attributes object * @param name the name of the attribute * @return the attribute value as an int array */
public static int[] getAttributeAsIntArray(Attributes attributes, String name) { String s = attributes.getValue(name); if (s == null) { return null; } else { return ConversionUtils.toIntArray(s.trim(), "\\s"); } }
Adds an attribute to a given AttributesImpl instance.
Params:
  • atts – the attributes collection
  • attribute – the attribute to add
  • value – the attribute's CDATA value
/** * Adds an attribute to a given {@link AttributesImpl} instance. * @param atts the attributes collection * @param attribute the attribute to add * @param value the attribute's CDATA value */
public static void addAttribute(AttributesImpl atts, org.apache.xmlgraphics.util.QName attribute, String value) { atts.addAttribute(attribute.getNamespaceURI(), attribute.getLocalName(), attribute.getQName(), XMLUtil.CDATA, value); }
Adds an attribute to a given AttributesImpl instance. The attribute will be added in the default namespace.
Params:
  • atts – the attributes collection
  • localName – the local name of the attribute
  • value – the attribute's CDATA value
/** * Adds an attribute to a given {@link AttributesImpl} instance. The attribute will be * added in the default namespace. * @param atts the attributes collection * @param localName the local name of the attribute * @param value the attribute's CDATA value */
public static void addAttribute(AttributesImpl atts, String localName, String value) { atts.addAttribute("", localName, localName, XMLUtil.CDATA, value); }
Encode a glyph position adjustments array as a string, where the string value adheres to the following syntax: count ( 'Z' repeat | number ) where each token is separated by whitespace, except that 'Z' followed by repeat are considered to be a single token with no intervening whitespace, and where 'Z' repeat encodes repeated zeroes.
Params:
  • dp – the adjustments array
  • paCount – the number of entries to encode from adjustments array
Returns:the encoded value
/** * Encode a glyph position adjustments array as a string, where the string value * adheres to the following syntax: * * count ( 'Z' repeat | number ) * * where each token is separated by whitespace, except that 'Z' followed by repeat * are considered to be a single token with no intervening whitespace, and where * 'Z' repeat encodes repeated zeroes. * @param dp the adjustments array * @param paCount the number of entries to encode from adjustments array * @return the encoded value */
public static String encodePositionAdjustments(int[][] dp, int paCount) { assert dp != null; StringBuffer sb = new StringBuffer(); int na = paCount; int nz = 0; sb.append(na); for (int i = 0; i < na; i++) { int[] pa = dp [ i ]; if (pa != null) { for (int k = 0; k < 4; k++) { int a = pa [ k ]; if (a != 0) { encodeNextAdjustment(sb, nz, a); nz = 0; } else { nz++; } } } else { nz += 4; } } encodeNextAdjustment(sb, nz, 0); return sb.toString(); }
Encode a glyph position adjustments array as a string, where the string value adheres to the following syntax: count ( 'Z' repeat | number ) where each token is separated by whitespace, except that 'Z' followed by repeat are considered to be a single token with no intervening whitespace.
Params:
  • dp – the adjustments array
Returns:the encoded value
/** * Encode a glyph position adjustments array as a string, where the string value * adheres to the following syntax: * * count ( 'Z' repeat | number ) * * where each token is separated by whitespace, except that 'Z' followed by repeat * are considered to be a single token with no intervening whitespace. * @param dp the adjustments array * @return the encoded value */
public static String encodePositionAdjustments(int[][] dp) { assert dp != null; return encodePositionAdjustments(dp, dp.length); } private static void encodeNextAdjustment(StringBuffer sb, int nz, int a) { encodeZeroes(sb, nz); encodeAdjustment(sb, a); } private static void encodeZeroes(StringBuffer sb, int nz) { if (nz > 0) { sb.append(' '); if (nz == 1) { sb.append('0'); } else { sb.append('Z'); sb.append(nz); } } } private static void encodeAdjustment(StringBuffer sb, int a) { if (a != 0) { sb.append(' '); sb.append(a); } }
Decode a string as a glyph position adjustments array, where the string shall adhere to the syntax specified by encodePositionAdjustments.
Params:
  • value – the encoded value
Returns:the position adjustments array
/** * Decode a string as a glyph position adjustments array, where the string * shall adhere to the syntax specified by {@link #encodePositionAdjustments}. * @param value the encoded value * @return the position adjustments array */
public static int[][] decodePositionAdjustments(String value) { int[][] dp = null; if (value != null) { String[] sa = value.split("\\s"); if (sa != null) { if (sa.length > 0) { int na = Integer.parseInt(sa[0]); dp = new int [ na ] [ 4 ]; for (int i = 1, n = sa.length, k = 0; i < n; i++) { String s = sa [ i ]; if (s.charAt(0) == 'Z') { int nz = Integer.parseInt(s.substring(1)); k += nz; } else { dp [ k / 4 ] [ k % 4 ] = Integer.parseInt(s); k += 1; } } } } } return dp; }
Returns an attribute value as a glyph position adjustments array. The string value is expected to be a non-empty sequence of either Z<repeat> or <number>, where the former encodes a repeat count (of zeroes) and the latter encodes a integer number, and where each item is separated by whitespace.
Params:
  • attributes – the Attributes object
  • name – the name of the attribute
Returns:the position adjustments array
/** * Returns an attribute value as a glyph position adjustments array. The string value * is expected to be a non-empty sequence of either Z&lt;repeat&gt; or &lt;number&gt;, where the * former encodes a repeat count (of zeroes) and the latter encodes a integer number, * and where each item is separated by whitespace. * @param attributes the Attributes object * @param name the name of the attribute * @return the position adjustments array */
public static int[][] getAttributeAsPositionAdjustments(Attributes attributes, String name) { String s = attributes.getValue(name); if (s == null) { return null; } else { return decodePositionAdjustments(s.trim()); } }
Escape '<', '>' and '&' using NCRs.
Params:
  • unescaped – string
Returns:escaped string
/** * Escape '&lt;', '&gt;' and '&amp;' using NCRs. * @param unescaped string * @return escaped string */
public static String escape(String unescaped) { int needsEscape = 0; for (int i = 0, n = unescaped.length(); i < n; ++i) { char c = unescaped.charAt(i); if ((c == '<') || (c == '>') || (c == '&')) { ++needsEscape; } } if (needsEscape > 0) { StringBuffer sb = new StringBuffer(unescaped.length() + 6 * needsEscape); for (int i = 0, n = unescaped.length(); i < n; ++i) { char c = unescaped.charAt(i); if ((c == '<') || (c == '>') || (c == '&')) { sb.append("&#x"); sb.append(Integer.toString(c, 16)); sb.append(';'); } else { sb.append(c); } } return sb.toString(); } else { return unescaped; } } }