📄 xmlutil.java
字号:
/*
* element used a non-prefixed name, distinguish between no namespace and
* default namespace
*/
if (StringUtils.isEmpty(namespaceURI)) {
// no namespace
target = addChildElement(parent, localName);
if (traceEnabled)
log.trace("appended element: " + localName);
}
else {
// default namespace, look for existing prefix at target
prefix = getPrefix(namespaceURI, parent);
// no prefix for that namespace?
if (prefix == null) {
prefix = generatePrefix(source, DEFAULT_NAMESPACE_PREFIX);
}
// BPEL-195 source maps prefix to another URI?
else if (!namespaceURI.equals(source.getAttributeNS(
BpelConstants.NS_XMLNS, prefix))) {
prefix = generatePrefix(source, prefix);
}
target = parent.addChildElement(localName, prefix, namespaceURI);
if (traceEnabled)
log.trace("added child element: {"
+ namespaceURI
+ '}'
+ prefix
+ ':'
+ localName);
}
}
else {
target = parent.addChildElement(localName, prefix, namespaceURI);
if (traceEnabled)
log.trace("added child element: {"
+ namespaceURI
+ '}'
+ prefix
+ ':'
+ localName);
}
// namespaces
copyNamespaces(target, source);
// attributes
copyAttributes(target, source);
// child nodes
copyChildNodes(target, source);
}
public static SOAPElement addChildElement(SOAPElement parent, String localName)
throws SOAPException {
// the proper call is addChildElement(localName); however, the WS4EE stack
// mistakenly adds a child element with parent's namespace URI
return parent.addChildElement(localName, "", "");
}
public static Node appendForeignChild(Node node, Node foreignChild) {
return node.appendChild(node.getOwnerDocument().importNode(foreignChild,
true));
}
public static void addNamespaceDeclaration(Element elem, String namespaceURI) {
elem.setAttributeNS(BpelConstants.NS_XMLNS, "xmlns", namespaceURI);
}
public static void addNamespaceDeclaration(Element elem, String namespaceURI,
String prefix) {
elem.setAttributeNS(BpelConstants.NS_XMLNS, "xmlns:" + prefix, namespaceURI);
}
public static void removeAttributes(Element elem) {
if (elem.hasAttributes()) {
NamedNodeMap attributeMap = elem.getAttributes();
// since node maps are live, we must hold them in a separate container
int n = attributeMap.getLength();
Attr[] attributes = new Attr[n];
for (int i = 0; i < n; i++) {
attributes[i] = (Attr) attributeMap.item(i);
}
// now remove each attribute from the element
for (int i = 0; i < n; i++) {
elem.removeAttributeNode(attributes[i]);
}
}
}
public static void removeChildNodes(Node node) {
for (Node current = node.getFirstChild(), next; current != null; current = next) {
next = current.getNextSibling();
node.removeChild(current);
}
}
public static void removeAttributes(SOAPElement elem) {
if (elem.hasAttributes()) {
Iterator attrNameIt = elem.getAllAttributes();
while (attrNameIt.hasNext()) {
Name attrName = (Name) attrNameIt.next();
elem.removeAttribute(attrName);
}
}
}
public static void removeNamespaces(SOAPElement elem) {
Iterator prefixIt = elem.getNamespacePrefixes();
while (prefixIt.hasNext()) {
String prefix = (String) prefixIt.next();
elem.removeNamespaceDeclaration(prefix);
}
}
public static Document createDocument() {
return getDocumentBuilder().newDocument();
}
public static Element createElement(QName name) {
String prefix = name.getPrefix();
if (prefix.length() == 0)
prefix = "defaultNS";
return createElement(name.getNamespaceURI(), prefix
+ ':'
+ name.getLocalPart());
}
public static Element createElement(String namespaceURI, String prefixedName) {
Document doc = createDocument();
Element elem = doc.createElementNS(namespaceURI, prefixedName);
doc.appendChild(elem);
// some TrAX implementations do not fix up namespaces, declare namespace
String prefix = elem.getPrefix();
if (prefix != null)
addNamespaceDeclaration(elem, namespaceURI, prefix);
else
addNamespaceDeclaration(elem, namespaceURI);
return elem;
}
public static Element createElement(String localName) {
Document doc = createDocument();
Element elem = doc.createElementNS(null, localName);
doc.appendChild(elem);
return elem;
}
/**
* Parses the XML document contained in the given string into a DOM document.
* @param text a string containing the document to parse
* @return a new DOM document representing the XML content
* @throws SAXException if any parse errors occur
*/
public static Element parseElement(String text) throws SAXException {
try {
return getDocumentBuilder().parse(new InputSource(new StringReader(text)))
.getDocumentElement();
}
catch (IOException e) {
throw new RuntimeException("IO error parsing a *string*", e);
}
}
/**
* Gets a validating document builder local to the current thread.
* @return a thread-local document builder
*/
public static DocumentBuilder getDocumentBuilder() {
return (DocumentBuilder) documentBuilderLocal.get();
}
public static Map getNamespaces(Element elem) {
HashMap namespaces = new HashMap();
try {
Navigator nav = DocumentNavigator.getInstance();
Iterator namespaceAxis = nav.getNamespaceAxisIterator(elem);
while (namespaceAxis.hasNext()) {
Object namespace = namespaceAxis.next();
String prefix = nav.getNamespacePrefix(namespace);
// exclude default namespaces and overriden namespaces
if (!StringUtils.isEmpty(prefix) && !namespaces.containsKey(prefix)) {
String uri = nav.getNamespaceStringValue(namespace);
namespaces.put(prefix, uri);
}
}
}
catch (UnsupportedAxisException e) {
log.fatal("Jaxen DOM navigator does not support the namespace axis, "
+ "cannot determine namespace declarations of DOM elements", e);
throw new AssertionError(e);
}
return namespaces;
}
/**
* Retrieves the prefix associated with a namespace URI in the given context
* node.
* @param namespaceURI the namespace whose prefix is required
* @param contextNode the node where to search for namespace declarations
* @return the prefix associated with the namespace URI; the empty string
* indicates the default namespace, while <code>null</code>
* indicates no association
*/
public static String getPrefix(String namespaceURI, Node contextNode) {
switch (contextNode.getNodeType()) {
case Node.ATTRIBUTE_NODE:
contextNode = ((Attr) contextNode).getOwnerElement();
break;
case Node.ELEMENT_NODE:
break;
default:
contextNode = contextNode.getParentNode();
}
while (contextNode != null
&& contextNode.getNodeType() == Node.ELEMENT_NODE) {
Element contextElem = (Element) contextNode;
NamedNodeMap attributes = contextElem.getAttributes();
for (int i = 0, n = attributes.getLength(); i < n; i++) {
Node attr = attributes.item(i);
if (namespaceURI.equals(attr.getNodeValue())) {
String prefix = attr.getPrefix();
if ("xmlns".equals(prefix)) {
return attr.getLocalName();
}
else if (prefix == null && "xmlns".equals(attr.getLocalName())) {
return "";
}
}
}
contextNode = contextNode.getParentNode();
}
return null;
}
public static String getPrefix(String namespaceURI, SOAPElement contextElem) {
Iterator prefixIt = contextElem.getVisibleNamespacePrefixes();
while (prefixIt.hasNext()) {
String prefix = (String) prefixIt.next();
if (namespaceURI.equals(contextElem.getNamespaceURI(prefix))) {
return prefix;
}
}
return null;
}
public static String getNamespaceURI(String prefix, Node contextNode) {
return DOMUtils.getNamespaceURIFromPrefix(contextNode, prefix);
}
private static String generatePrefix(Element contextElem, String baseText) {
// check possible collision with namespace declarations
if (!contextElem.hasAttributeNS(BpelConstants.NS_XMLNS, baseText))
return baseText;
// collision detected, append natural numbers
StringBuffer prefixBuffer = new StringBuffer(baseText);
int baseLength = baseText.length();
for (int i = 1; i < Integer.MAX_VALUE; i++) {
// append natural number to base text
String prefix = prefixBuffer.append(i).toString();
// check possible collision with namespace declarations
if (!contextElem.hasAttributeNS(BpelConstants.NS_XMLNS, prefix))
return prefix;
// remove appended number
prefixBuffer.setLength(baseLength);
}
throw new RuntimeException("could not generate prefix");
}
/**
* Evaluates the given XPath expression with the specified context node and
* namespace declarations.
* @param text the textual representation of an XPath expression
* @param context the context node
* @param namespaces the namespace declarations: prefix -> namespace URI
* @return the result value: a {@link java.lang.String},
* {@link java.lang.Double}, {@link Boolean} or nodeset; in the last
* case, the object returned depends on the set size: <table>
* <tr>
* <th>size</th>
* <th>object</th>
* </tr>
* <tr>
* <td>0</td>
* <td><code>null</code></td>
* </tr>
* <tr>
* <td>1</td>
* <td>a {@link Node}</td>
* </tr>
* <tr>
* <td>2+</td>
* <td>a {@link List} of nodes</td>
* </tr>
* </table>
*/
public static Object evaluateXPath(String text, Node context, Map namespaces) {
try {
XPath xpath = new DOMXPath(text);
if (namespaces != null) {
xpath.setNamespaceContext(new SimpleNamespaceContext(namespaces));
}
Object result = xpath.evaluate(context);
if (result instanceof List) {
List nodeset = (List) result;
switch (nodeset.size()) {
case 0:
result = null;
break;
case 1:
result = nodeset.get(0);
break;
}
}
return result;
}
catch (JaxenException e) {
throw new RuntimeException("could not evaluate XPath", e);
}
}
public static TransformerFactory getTransformerFactory() {
return (TransformerFactory) transformerFactoryLocal.get();
}
public static Templates createTemplates(URL templateURL) {
Templates templates = null;
try {
InputStream templateStream = templateURL.openStream();
templates = getTransformerFactory().newTemplates(
new StreamSource(templateStream));
templateStream.close();
}
catch (Exception e) {
log.error("unable to read templates: " + templateURL, e);
}
return templates;
}
private static class NamespaceElementPredicate implements Predicate {
private final String namespaceURI;
NamespaceElementPredicate(String namespaceURI) {
this.namespaceURI = namespaceURI;
}
public boolean evaluate(Object arg) {
return evaluate((Node) arg, namespaceURI);
}
static boolean evaluate(Node node, String namespaceURI) {
String nodeNamespaceURI = node.getNamespaceURI();
return node.getNodeType() == Node.ELEMENT_NODE
&& (namespaceURI != null ? namespaceURI.equals(nodeNamespaceURI)
: StringUtils.isEmpty(nodeNamespaceURI));
}
}
private static class QNameElementPredicate implements Predicate {
private final String namespaceURI;
private final String localName;
QNameElementPredicate(String namespaceURI, String localName) {
this.namespaceURI = namespaceURI;
this.localName = localName;
}
public boolean evaluate(Object arg) {
return evaluate((Node) arg, namespaceURI, localName);
}
static boolean evaluate(Node node, String namespaceURI, String localName) {
return NamespaceElementPredicate.evaluate(node, namespaceURI)
&& localName.equals(node.getLocalName());
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -