下面列出了org.w3c.dom.Element#hasAttributeNS ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static String getAttribute(Element e, QName qn, String defaultValue) {
String ns = qn.getNamespaceURI();
String ln = qn.getLocalPart();
String value;
if ((ns == null) || (ns.length() == 0)) {
if (e.hasAttribute(ln))
value = e.getAttribute(ln);
else
value = defaultValue;
} else {
if (e.hasAttributeNS(ns, ln))
value = e.getAttributeNS(ns, ln);
else
value = defaultValue;
}
return value;
}
protected void namespace(Element element, String prefix, String uri) {
String qname;
if ("".equals(prefix) || prefix == null) {
qname = "xmlns";
} else {
qname = "xmlns:" + prefix;
}
// older version of Xerces (I confirmed that the bug is gone with Xerces 2.4.0)
// have a problem of re-setting the same namespace attribute twice.
// work around this bug removing it first.
if (element.hasAttributeNS("http://www.w3.org/2000/xmlns/", qname)) {
// further workaround for an old Crimson bug where the removeAttribtueNS
// method throws NPE when the element doesn't have any attribute.
// to be on the safe side, check the existence of attributes before
// attempting to remove it.
// for details about this bug, see org.apache.crimson.tree.ElementNode2
// line 540 or the following message:
// https://jaxb.dev.java.net/servlets/ReadMsg?list=users&msgNo=2767
element.removeAttributeNS("http://www.w3.org/2000/xmlns/", qname);
}
// workaround until here
element.setAttributeNS("http://www.w3.org/2000/xmlns/", qname, uri);
}
protected String getUnusedGenericNsPrefix() {
synchronized(document) {
Element documentElement = document.getDocumentElement();
if (documentElement == null) {
return GENERIC_NS_PREFIX + "0";
}
else {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
if (!documentElement.hasAttributeNS(XMLNS_ATTRIBUTE_NS_URI, GENERIC_NS_PREFIX + i)) {
return GENERIC_NS_PREFIX + i;
}
}
throw new ModelException("Unable to find an unused namespace prefix");
}
}
}
protected void namespace(Element element, String prefix, String uri) {
String qname;
if ("".equals(prefix) || prefix == null) {
qname = "xmlns";
} else {
qname = "xmlns:" + prefix;
}
// older version of Xerces (I confirmed that the bug is gone with Xerces 2.4.0)
// have a problem of re-setting the same namespace attribute twice.
// work around this bug removing it first.
if (element.hasAttributeNS("http://www.w3.org/2000/xmlns/", qname)) {
// further workaround for an old Crimson bug where the removeAttribtueNS
// method throws NPE when the element doesn't have any attribute.
// to be on the safe side, check the existence of attributes before
// attempting to remove it.
// for details about this bug, see org.apache.crimson.tree.ElementNode2
// line 540 or the following message:
// https://jaxb.dev.java.net/servlets/ReadMsg?list=users&msgNo=2767
element.removeAttributeNS("http://www.w3.org/2000/xmlns/", qname);
}
// workaround until here
element.setAttributeNS("http://www.w3.org/2000/xmlns/", qname, uri);
}
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
if (!element.hasAttributeNS(ANDROID_URI, ATTR_CONTENT_DESCRIPTION)) {
// Ignore views that are explicitly not important for accessibility
if (VALUE_NO.equals(element.getAttributeNS(ANDROID_URI,
ATTR_IMPORTANT_FOR_ACCESSIBILITY))) {
return;
}
context.report(ISSUE, element, context.getLocation(element),
"[Accessibility] Missing `contentDescription` attribute on image");
} else {
Attr attributeNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_CONTENT_DESCRIPTION);
String attribute = attributeNode.getValue();
if (attribute.isEmpty() || attribute.equals("TODO")) { //$NON-NLS-1$
context.report(ISSUE, attributeNode, context.getLocation(attributeNode),
"[Accessibility] Empty `contentDescription` attribute on image");
}
}
}
protected String findIDFromSamlToken(Element samlToken) {
String id = null;
if (samlToken != null) {
QName elName = DOMUtils.getElementQName(samlToken);
if (elName.equals(new QName(WSConstants.SAML_NS, "Assertion"))
&& samlToken.hasAttributeNS(null, "AssertionID")) {
id = samlToken.getAttributeNS(null, "AssertionID");
} else if (elName.equals(new QName(WSConstants.SAML2_NS, "Assertion"))
&& samlToken.hasAttributeNS(null, "ID")) {
id = samlToken.getAttributeNS(null, "ID");
}
if (id == null) {
id = samlToken.getAttributeNS(WSConstants.WSU_NS, "Id");
}
}
return id;
}
protected void namespace(Element element, String prefix, String uri) {
String qname;
if ("".equals(prefix) || prefix == null) {
qname = "xmlns";
} else {
qname = "xmlns:" + prefix;
}
// older version of Xerces (I confirmed that the bug is gone with Xerces 2.4.0)
// have a problem of re-setting the same namespace attribute twice.
// work around this bug removing it first.
if (element.hasAttributeNS("http://www.w3.org/2000/xmlns/", qname)) {
// further workaround for an old Crimson bug where the removeAttribtueNS
// method throws NPE when the element doesn't have any attribute.
// to be on the safe side, check the existence of attributes before
// attempting to remove it.
// for details about this bug, see org.apache.crimson.tree.ElementNode2
// line 540 or the following message:
// https://jaxb.dev.java.net/servlets/ReadMsg?list=users&msgNo=2767
element.removeAttributeNS("http://www.w3.org/2000/xmlns/", qname);
}
// workaround until here
element.setAttributeNS("http://www.w3.org/2000/xmlns/", qname, uri);
}
private static boolean hasSpecifiedAttributes(Element el) {
NamedNodeMap attrs = el.getAttributes();
for (int i = 0, n = attrs.getLength(); i < n; ++i) {
Attr a = (Attr) attrs.item(i);
if (el.hasAttributeNS(a.getNamespaceURI(), a.getLocalName())) {
return true;
}
}
return false;
}
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
String tag = element.getTagName();
if (tag.equals(TAG_STYLE)) {
scanTheme(element);
} else if (tag.equals(TAG_ACTIVITY)) {
scanActivity(context, element);
} else if (tag.equals(TAG_APPLICATION)) {
if (element.hasAttributeNS(ANDROID_URI, ATTR_THEME)) {
mManifestTheme = element.getAttributeNS(ANDROID_URI, ATTR_THEME);
}
} else if (tag.equals(TAG_BITMAP)) {
scanBitmap(context, element);
}
}
/**
* Removes all subelements with xsi:nil attribute as they are worthless.
*
* JAXB optimizes namespace declarations and moves them to common parent elements
* but Fedora ingest ignores it. Then some ingested datastreams may be broken
* as they miss optimized namespace declarations (xsi in this case).
*/
public static void removeNils(Element elm) {
NodeList children = elm.getChildNodes();
for (int i = children.getLength() - 1; i >= 0; i--) {
Node item = children.item(i);
if (item.getNodeType() == Node.ELEMENT_NODE) {
Element itemElm = (Element) item;
if (itemElm.hasAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil")) {
itemElm.getParentNode().removeChild(item);
} else {
removeNils(itemElm);
}
}
}
}
private String getIdFromToken(Element token) {
if (token != null) {
// Try to find the "Id" on the token.
if (token.hasAttributeNS(WSConstants.WSU_NS, "Id")) {
return token.getAttributeNS(WSConstants.WSU_NS, "Id");
} else if (token.hasAttributeNS(null, "ID")) {
return token.getAttributeNS(null, "ID");
} else if (token.hasAttributeNS(null, "AssertionID")) {
return token.getAttributeNS(null, "AssertionID");
}
}
return "";
}
/**
* Returns whether the given issue is suppressed in the given XML DOM node.
*
* @param issue the issue to be checked, or null to just check for "all"
* @param node the DOM node containing the issue
* @return true if there is a suppress annotation covering the specific
* issue in this class
*/
public boolean isSuppressed(@Nullable XmlContext context, @NonNull Issue issue,
@Nullable org.w3c.dom.Node node) {
if (node instanceof Attr) {
node = ((Attr) node).getOwnerElement();
}
boolean checkComments = mClient.checkForSuppressComments()
&& context != null && context.containsCommentSuppress();
while (node != null) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
Element element = (Element) node;
if (element.hasAttributeNS(TOOLS_URI, ATTR_IGNORE)) {
String ignore = element.getAttributeNS(TOOLS_URI, ATTR_IGNORE);
if (ignore.indexOf(',') == -1) {
if (matches(issue, ignore)) {
return true;
}
} else {
for (String id : ignore.split(",")) { //$NON-NLS-1$
if (matches(issue, id)) {
return true;
}
}
}
} else if (checkComments && context.isSuppressedWithComment(node, issue)) {
return true;
}
}
node = node.getParentNode();
}
return false;
}
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
if (element.getTagName().equals(TEXT_VIEW)) {
if (!element.hasAttributeNS(ANDROID_URI, ATTR_TEXT)
&& element.hasAttributeNS(ANDROID_URI, ATTR_ID)
&& !element.hasAttributeNS(ANDROID_URI, ATTR_TEXT_IS_SELECTABLE)
&& !element.hasAttributeNS(ANDROID_URI, ATTR_VISIBILITY)
&& !element.hasAttributeNS(ANDROID_URI, ATTR_ON_CLICK)
&& context.getMainProject().getTargetSdk() >= 11
&& context.isEnabled(SELECTABLE)) {
context.report(SELECTABLE, element, context.getLocation(element),
"Consider making the text value selectable by specifying " +
"`android:textIsSelectable=\"true\"`");
}
}
NamedNodeMap attributes = element.getAttributes();
for (int i = 0, n = attributes.getLength(); i < n; i++) {
Attr attribute = (Attr) attributes.item(i);
String name = attribute.getLocalName();
if (name == null || name.isEmpty()) {
// Attribute not in a namespace; we only care about the android: ones
continue;
}
boolean isEditAttribute = false;
switch (name.charAt(0)) {
case 'a': {
isEditAttribute = name.equals(ATTR_AUTO_TEXT);
break;
}
case 'b': {
isEditAttribute = name.equals(ATTR_BUFFER_TYPE) &&
attribute.getValue().equals(VALUE_EDITABLE);
break;
}
case 'p': {
isEditAttribute = name.equals(ATTR_PASSWORD)
|| name.equals(ATTR_PHONE_NUMBER)
|| name.equals(ATTR_PRIVATE_IME_OPTIONS);
break;
}
case 'c': {
isEditAttribute = name.equals(ATTR_CAPITALIZE)
|| name.equals(ATTR_CURSOR_VISIBLE);
break;
}
case 'd': {
isEditAttribute = name.equals(ATTR_DIGITS);
break;
}
case 'e': {
if (name.equals(ATTR_EDITABLE)) {
isEditAttribute = attribute.getValue().equals(VALUE_TRUE);
} else {
isEditAttribute = name.equals(ATTR_EDITOR_EXTRAS);
}
break;
}
case 'i': {
if (name.equals(ATTR_INPUT_TYPE)) {
String value = attribute.getValue();
isEditAttribute = !value.isEmpty() && !value.equals(VALUE_NONE);
} else {
isEditAttribute = name.equals(ATTR_INPUT_TYPE)
|| name.equals(ATTR_IME_OPTIONS)
|| name.equals(ATTR_IME_ACTION_LABEL)
|| name.equals(ATTR_IME_ACTION_ID)
|| name.equals(ATTR_INPUT_METHOD);
}
break;
}
case 'n': {
isEditAttribute = name.equals(ATTR_NUMERIC);
break;
}
}
if (isEditAttribute && ANDROID_URI.equals(attribute.getNamespaceURI()) && context.isEnabled(ISSUE)) {
Location location = context.getLocation(attribute);
String message;
String view = element.getTagName();
if (view.equals(TEXT_VIEW)) {
message = String.format(
"Attribute `%1$s` should not be used with `<TextView>`: " +
"Change element type to `<EditText>` ?", attribute.getName());
} else {
message = String.format(
"Attribute `%1$s` should not be used with `<%2$s>`: " +
"intended for editable text widgets",
attribute.getName(), view);
}
context.report(ISSUE, attribute, location, message);
}
}
}
private void receivePropertiesImpl(Document document) {
DocumentProperties properties = getProperties();
properties.clear();
if (document == null)
return;
Node propertyContainer = document.getElementsByTagNameNS(PROPERTY_API_NS, "properties").item(0);
if (propertyContainer == null)
return;
NodeList propertiesIn = propertyContainer.getChildNodes();
for (int i=0; i < propertiesIn.getLength(); i++) {
Node node = propertiesIn.item(i);
if (node.getNodeType() != Node.ELEMENT_NODE)
continue;
Element property = (Element) node;
QName propertyName = null;
String namespaceURI = property.getNamespaceURI();
if (namespaceURI != null) {
String prefix = property.getPrefix();
if (prefix != null) {
propertyName = new QName(namespaceURI, property.getLocalName(), prefix);
} else {
propertyName = new QName(namespaceURI, property.getTagName());
}
} else {
propertyName = new QName(property.getTagName());
}
if (!property.hasChildNodes()) {
properties.put(propertyName, (String) null);
continue;
}
NodeList children = property.getChildNodes();
boolean hasChildElements = false;
int childCount = children.getLength();
for (int j=0; j < childCount; j++) {
Node child = children.item(j);
if (child.getNodeType() == Node.ELEMENT_NODE) {
hasChildElements = true;
break;
}
}
if (hasChildElements) {
properties.put(propertyName, children);
continue;
}
// TODO: casting known properties such as prop:last-modified
String value = property.getTextContent();
if (property.hasAttributeNS(
XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type")) {
String type = property.getAttributeNS(
XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
properties.put(propertyName, ValueConverter.convertToJava(type, value));
continue;
} else {
properties.put(propertyName, value);
}
properties.put(propertyName, value);
}
}
/**
* This is the work horse for {@link #circumventBug2650}.
*
* @param node
* @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
* Namespace axis resolution is not XPath compliant </A>
*/
@SuppressWarnings("fallthrough")
private static void circumventBug2650internal(Node node) {
Node parent = null;
Node sibling = null;
final String namespaceNs = Constants.NamespaceSpecNS;
do {
switch (node.getNodeType()) {
case Node.ELEMENT_NODE :
Element element = (Element) node;
if (!element.hasChildNodes()) {
break;
}
if (element.hasAttributes()) {
NamedNodeMap attributes = element.getAttributes();
int attributesLength = attributes.getLength();
for (Node child = element.getFirstChild(); child!=null;
child = child.getNextSibling()) {
if (child.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
Element childElement = (Element) child;
for (int i = 0; i < attributesLength; i++) {
Attr currentAttr = (Attr) attributes.item(i);
if (!namespaceNs.equals(currentAttr.getNamespaceURI())) {
continue;
}
if (childElement.hasAttributeNS(namespaceNs,
currentAttr.getLocalName())) {
continue;
}
childElement.setAttributeNS(namespaceNs,
currentAttr.getName(),
currentAttr.getNodeValue());
}
}
}
case Node.ENTITY_REFERENCE_NODE :
case Node.DOCUMENT_NODE :
parent = node;
sibling = node.getFirstChild();
break;
}
while ((sibling == null) && (parent != null)) {
sibling = parent.getNextSibling();
parent = parent.getParentNode();
}
if (sibling == null) {
return;
}
node = sibling;
sibling = node.getNextSibling();
} while (true);
}
private boolean hasInstance(Element element) {
return element.hasAttributeNS(XmlPreProcessor.deployNamespaceUri, INSTANCE_ATTRIBUTE);
}
/**
* This is the work horse for {@link #circumventBug2650}.
*
* @param node
* @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
* Namespace axis resolution is not XPath compliant </A>
*/
@SuppressWarnings("fallthrough")
private static void circumventBug2650internal(Node node) {
Node parent = null;
Node sibling = null;
final String namespaceNs = Constants.NamespaceSpecNS;
do {
switch (node.getNodeType()) {
case Node.ELEMENT_NODE :
Element element = (Element) node;
if (!element.hasChildNodes()) {
break;
}
if (element.hasAttributes()) {
NamedNodeMap attributes = element.getAttributes();
int attributesLength = attributes.getLength();
for (Node child = element.getFirstChild(); child!=null;
child = child.getNextSibling()) {
if (child.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
Element childElement = (Element) child;
for (int i = 0; i < attributesLength; i++) {
Attr currentAttr = (Attr) attributes.item(i);
if (!namespaceNs.equals(currentAttr.getNamespaceURI())) {
continue;
}
if (childElement.hasAttributeNS(namespaceNs,
currentAttr.getLocalName())) {
continue;
}
childElement.setAttributeNS(namespaceNs,
currentAttr.getName(),
currentAttr.getNodeValue());
}
}
}
case Node.ENTITY_REFERENCE_NODE :
case Node.DOCUMENT_NODE :
parent = node;
sibling = node.getFirstChild();
break;
}
while ((sibling == null) && (parent != null)) {
sibling = parent.getNextSibling();
parent = parent.getParentNode();
}
if (sibling == null) {
return;
}
node = sibling;
sibling = node.getNextSibling();
} while (true);
}
/**
* This is the work horse for {@link #circumventBug2650}.
*
* @param node
* @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
* Namespace axis resolution is not XPath compliant </A>
*/
@SuppressWarnings("fallthrough")
private static void circumventBug2650internal(Node node) {
Node parent = null;
Node sibling = null;
final String namespaceNs = Constants.NamespaceSpecNS;
do {
switch (node.getNodeType()) {
case Node.ELEMENT_NODE :
Element element = (Element) node;
if (!element.hasChildNodes()) {
break;
}
if (element.hasAttributes()) {
NamedNodeMap attributes = element.getAttributes();
int attributesLength = attributes.getLength();
for (Node child = element.getFirstChild(); child!=null;
child = child.getNextSibling()) {
if (child.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
Element childElement = (Element) child;
for (int i = 0; i < attributesLength; i++) {
Attr currentAttr = (Attr) attributes.item(i);
if (!namespaceNs.equals(currentAttr.getNamespaceURI())) {
continue;
}
if (childElement.hasAttributeNS(namespaceNs,
currentAttr.getLocalName())) {
continue;
}
childElement.setAttributeNS(namespaceNs,
currentAttr.getName(),
currentAttr.getNodeValue());
}
}
}
case Node.ENTITY_REFERENCE_NODE :
case Node.DOCUMENT_NODE :
parent = node;
sibling = node.getFirstChild();
break;
}
while ((sibling == null) && (parent != null)) {
sibling = parent.getNextSibling();
parent = parent.getParentNode();
}
if (sibling == null) {
return;
}
node = sibling;
sibling = node.getNextSibling();
} while (true);
}
@Override
public void afterCheckFile(@NonNull Context context) {
if (mTextFields != null) {
if (mLabels == null) {
mLabels = Collections.emptySet();
}
for (Element element : mTextFields) {
if (element.hasAttributeNS(ANDROID_URI, ATTR_HINT)) {
continue;
}
String id = element.getAttributeNS(ANDROID_URI, ATTR_ID);
boolean missing = true;
if (mLabels.contains(id)) {
missing = false;
} else if (id.startsWith(NEW_ID_PREFIX)) {
missing = !mLabels.contains(ID_PREFIX + stripIdPrefix(id));
} else if (id.startsWith(ID_PREFIX)) {
missing = !mLabels.contains(NEW_ID_PREFIX + stripIdPrefix(id));
}
if (missing) {
XmlContext xmlContext = (XmlContext) context;
Location location = xmlContext.getLocation(element);
String message;
if (id == null || id.isEmpty()) {
message = "No label views point to this text field with a " +
"`labelFor` attribute";
} else {
message = String.format("No label views point to this text field with " +
"an `android:labelFor=\"@+id/%1$s\"` attribute", id);
}
xmlContext.report(ISSUE, element, location, message);
}
}
}
mLabels = null;
mTextFields = null;
}
/**
* This is the work horse for {@link #circumventBug2650}.
*
* @param node
* @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
* Namespace axis resolution is not XPath compliant </A>
*/
@SuppressWarnings("fallthrough")
private static void circumventBug2650internal(Node node) {
Node parent = null;
Node sibling = null;
final String namespaceNs = Constants.NamespaceSpecNS;
do {
switch (node.getNodeType()) {
case Node.ELEMENT_NODE :
Element element = (Element) node;
if (!element.hasChildNodes()) {
break;
}
if (element.hasAttributes()) {
NamedNodeMap attributes = element.getAttributes();
int attributesLength = attributes.getLength();
for (Node child = element.getFirstChild(); child!=null;
child = child.getNextSibling()) {
if (child.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
Element childElement = (Element) child;
for (int i = 0; i < attributesLength; i++) {
Attr currentAttr = (Attr) attributes.item(i);
if (!namespaceNs.equals(currentAttr.getNamespaceURI())) {
continue;
}
if (childElement.hasAttributeNS(namespaceNs,
currentAttr.getLocalName())) {
continue;
}
childElement.setAttributeNS(namespaceNs,
currentAttr.getName(),
currentAttr.getNodeValue());
}
}
}
case Node.ENTITY_REFERENCE_NODE :
case Node.DOCUMENT_NODE :
parent = node;
sibling = node.getFirstChild();
break;
}
while ((sibling == null) && (parent != null)) {
sibling = parent.getNextSibling();
parent = parent.getParentNode();
}
if (sibling == null) {
return;
}
node = sibling;
sibling = node.getNextSibling();
} while (true);
}