Implement GetElementsByAttributeNS. Bug 239976, patch by Joerg Bornemann

<jobor@gmx.de>, r+sr=bzbarsky
This commit is contained in:
bzbarsky%mit.edu 2006-09-14 04:29:02 +00:00
Родитель 8eea851320
Коммит 81e8fa73b3
7 изменённых файлов: 190 добавлений и 19 удалений

Просмотреть файл

@ -2759,8 +2759,6 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
{ {
PRInt32 nameSpaceId = kNameSpaceID_Wildcard; PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
nsContentList *list = nsnull;
if (!aNamespaceURI.EqualsLiteral("*")) { if (!aNamespaceURI.EqualsLiteral("*")) {
nsresult rv = nsresult rv =
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
@ -2768,13 +2766,11 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
if (!list) { nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName); NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
list = NS_GetContentList(this, nameAtom, nameSpaceId).get(); nsContentList *list = NS_GetContentList(this, nameAtom, nameSpaceId).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
}
// transfer ref to aReturn // transfer ref to aReturn
*aReturn = list; *aReturn = list;

Просмотреть файл

@ -1639,8 +1639,6 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
{ {
PRInt32 nameSpaceId = kNameSpaceID_Wildcard; PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
nsContentList *list = nsnull;
if (!aNamespaceURI.EqualsLiteral("*")) { if (!aNamespaceURI.EqualsLiteral("*")) {
nsresult rv = nsresult rv =
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
@ -1648,13 +1646,11 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
if (!list) { nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName); NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
list = NS_GetContentList(this, nameAtom, nameSpaceId).get(); nsContentList *list = NS_GetContentList(this, nameAtom, nameSpaceId).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
}
// transfer ref to aReturn // transfer ref to aReturn
*aReturn = list; *aReturn = list;

Просмотреть файл

@ -10,6 +10,7 @@ function run_test()
test_getElementsByTagName(); test_getElementsByTagName();
test_getElementsByTagNameNS(); test_getElementsByTagNameNS();
test_getElementsByAttribute(); test_getElementsByAttribute();
test_getElementsByAttributeNS();
// What else should we test? // What else should we test?
// XXXbz we need more tests here to test liveness! // XXXbz we need more tests here to test liveness!
@ -282,3 +283,112 @@ function test_getElementsByAttribute()
do_check_eq(root.getElementsByAttribute("foo:foo", "baz").length, do_check_eq(root.getElementsByAttribute("foo:foo", "baz").length,
0); 0);
} }
function test_getElementsByAttributeNS()
{
var doc = ParseFile("nodelist_data_2.xul");
var root = doc.documentElement;
// Sadly, DOMParser can't create XULDocument objects. But at least we have a
// XULElement!
do_check_true(root instanceof nsIDOMXULElement);
// Check that getElementsByAttributeNS returns a nodelist.
do_check_true(root.getElementsByAttributeNS("*", "*", "*") instanceof
nsIDOMNodeList);
var master1 = doc.getElementById("master1");
var master2 = doc.getElementById("master2");
var master3 = doc.getElementById("master3");
var external = doc.getElementById("external");
do_check_true(master1 instanceof nsIDOMXULElement);
do_check_true(master2 instanceof nsIDOMXULElement);
do_check_true(master3 instanceof nsIDOMXULElement);
do_check_true(external instanceof nsIDOMXULElement);
// Test wildcard namespace
do_check_eq(root.getElementsByAttributeNS("*", "foo", "foo").length,
38);
do_check_eq(master1.getElementsByAttributeNS("*", "foo", "foo").length,
11);
do_check_eq(master2.getElementsByAttributeNS("*", "foo", "foo").length,
10);
do_check_eq(master3.getElementsByAttributeNS("*", "foo", "foo").length,
11);
do_check_eq(root.getElementsByAttributeNS("*", "foo", "bar").length,
16);
do_check_eq(master1.getElementsByAttributeNS("*", "foo", "bar").length,
4);
do_check_eq(master2.getElementsByAttributeNS("*", "foo", "bar").length,
5);
do_check_eq(master3.getElementsByAttributeNS("*", "foo", "bar").length,
4);
do_check_eq(root.getElementsByAttributeNS("*", "bar", "bar").length,
21);
do_check_eq(master1.getElementsByAttributeNS("*", "bar", "bar").length,
6);
do_check_eq(master2.getElementsByAttributeNS("*", "bar", "bar").length,
6);
do_check_eq(master3.getElementsByAttributeNS("*", "bar", "bar").length,
6);
do_check_eq(root.getElementsByAttributeNS("*", "foo", "*").length,
54);
do_check_eq(master1.getElementsByAttributeNS("*", "foo", "*").length,
15);
do_check_eq(master2.getElementsByAttributeNS("*", "foo", "*").length,
15);
do_check_eq(master3.getElementsByAttributeNS("*", "foo", "*").length,
15);
// Test null namespace. This should be the same as getElementsByAttribute.
do_check_eq(root.getElementsByAttributeNS("", "foo", "foo").length,
root.getElementsByAttribute("foo", "foo").length);
do_check_eq(master1.getElementsByAttributeNS("", "foo", "foo").length,
master1.getElementsByAttribute("foo", "foo").length);
do_check_eq(master2.getElementsByAttributeNS("", "foo", "foo").length,
master2.getElementsByAttribute("foo", "foo").length);
do_check_eq(master3.getElementsByAttributeNS("", "foo", "foo").length,
master3.getElementsByAttribute("foo", "foo").length);
// Test namespace "foo"
do_check_eq(root.getElementsByAttributeNS("foo", "foo", "foo").length,
24);
do_check_eq(master1.getElementsByAttributeNS("foo", "foo", "foo").length,
7);
do_check_eq(master2.getElementsByAttributeNS("foo", "foo", "foo").length,
6);
do_check_eq(master3.getElementsByAttributeNS("foo", "foo", "foo").length,
7);
do_check_eq(root.getElementsByAttributeNS("foo", "foo", "bar").length,
9);
do_check_eq(master1.getElementsByAttributeNS("foo", "foo", "bar").length,
2);
do_check_eq(master2.getElementsByAttributeNS("foo", "foo", "bar").length,
3);
do_check_eq(master3.getElementsByAttributeNS("foo", "foo", "bar").length,
2);
do_check_eq(root.getElementsByAttributeNS("foo", "bar", "foo").length,
7);
do_check_eq(master1.getElementsByAttributeNS("foo", "bar", "foo").length,
2);
do_check_eq(master2.getElementsByAttributeNS("foo", "bar", "foo").length,
2);
do_check_eq(master3.getElementsByAttributeNS("foo", "bar", "foo").length,
2);
do_check_eq(root.getElementsByAttributeNS("foo", "bar", "bar").length,
14);
do_check_eq(master1.getElementsByAttributeNS("foo", "bar", "bar").length,
4);
do_check_eq(master2.getElementsByAttributeNS("foo", "bar", "bar").length,
4);
do_check_eq(master3.getElementsByAttributeNS("foo", "bar", "bar").length,
4);
}

Просмотреть файл

@ -516,6 +516,36 @@ nsXULElement::GetElementsByAttribute(const nsAString& aAttribute,
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
const nsAString& aAttribute,
const nsAString& aValue,
nsIDOMNodeList** aReturn)
{
nsCOMPtr<nsIAtom> attrAtom(do_GetAtom(aAttribute));
NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
if (!aNamespaceURI.EqualsLiteral("*")) {
nsresult rv =
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
nameSpaceId);
NS_ENSURE_SUCCESS(rv, rv);
}
nsContentList *list =
new nsContentList(this,
nsXULDocument::MatchAttribute,
aValue,
PR_TRUE,
attrAtom,
nameSpaceId);
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aReturn = list);
return NS_OK;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsIXMLContent interface // nsIXMLContent interface

Просмотреть файл

@ -1150,6 +1150,34 @@ nsXULDocument::GetElementsByAttribute(const nsAString& aAttribute,
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsXULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI,
const nsAString& aAttribute,
const nsAString& aValue,
nsIDOMNodeList** aReturn)
{
nsCOMPtr<nsIAtom> attrAtom(do_GetAtom(aAttribute));
NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
if (!aNamespaceURI.EqualsLiteral("*")) {
nsresult rv =
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
nameSpaceId);
NS_ENSURE_SUCCESS(rv, rv);
}
nsContentList *list = new nsContentList(this,
MatchAttribute,
aValue,
PR_TRUE,
attrAtom,
nameSpaceId);
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aReturn = list);
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsXULDocument::Persist(const nsAString& aID, nsXULDocument::Persist(const nsAString& aID,
@ -2005,7 +2033,8 @@ nsXULDocument::MatchAttribute(nsIContent* aContent,
{ {
NS_PRECONDITION(aContent, "Must have content node to work with!"); NS_PRECONDITION(aContent, "Must have content node to work with!");
if (aNamespaceID != kNameSpaceID_Unknown) { if (aNamespaceID != kNameSpaceID_Unknown &&
aNamespaceID != kNameSpaceID_Wildcard) {
return aAttrValue.EqualsLiteral("*") ? return aAttrValue.EqualsLiteral("*") ?
aContent->HasAttr(aNamespaceID, aAttrName) : aContent->HasAttr(aNamespaceID, aAttrName) :
aContent->AttrValueIs(aNamespaceID, aAttrName, aAttrValue, aContent->AttrValueIs(aNamespaceID, aAttrName, aAttrValue,
@ -2020,6 +2049,8 @@ nsXULDocument::MatchAttribute(nsIContent* aContent,
PRBool nameMatch; PRBool nameMatch;
if (name->IsAtom()) { if (name->IsAtom()) {
nameMatch = name->Atom() == aAttrName; nameMatch = name->Atom() == aAttrName;
} else if (aNamespaceID == kNameSpaceID_Wildcard) {
nameMatch = name->NodeInfo()->Equals(aAttrName);
} else { } else {
nameMatch = name->NodeInfo()->QualifiedNameEquals(aAttrName); nameMatch = name->NodeInfo()->QualifiedNameEquals(aAttrName);
} }

Просмотреть файл

@ -42,7 +42,7 @@
interface nsIDOMXULCommandDispatcher; interface nsIDOMXULCommandDispatcher;
interface nsIObserver; interface nsIObserver;
[scriptable, uuid(a521baa9-0745-453a-9049-03c1a2241378)] [scriptable, uuid(9816241b-2a20-44ff-903b-575f40c0ecc5)]
interface nsIDOMXULDocument : nsISupports interface nsIDOMXULDocument : nsISupports
{ {
attribute nsIDOMNode popupNode; attribute nsIDOMNode popupNode;
@ -66,6 +66,10 @@ interface nsIDOMXULDocument : nsISupports
nsIDOMNodeList getElementsByAttribute(in DOMString name, nsIDOMNodeList getElementsByAttribute(in DOMString name,
in DOMString value); in DOMString value);
nsIDOMNodeList getElementsByAttributeNS(in DOMString namespaceURI,
in DOMString name,
in DOMString value);
void addBroadcastListenerFor(in nsIDOMElement broadcaster, void addBroadcastListenerFor(in nsIDOMElement broadcaster,
in nsIDOMElement observer, in nsIDOMElement observer,
in DOMString attr); in DOMString attr);

Просмотреть файл

@ -46,7 +46,7 @@ interface nsIControllers;
interface nsIBoxObject; interface nsIBoxObject;
[scriptable, uuid(0574ed81-c088-11d2-96ed-00104b7b7deb)] [scriptable, uuid(2261a45f-0a8f-401a-8e90-8da0d26cf9e3)]
interface nsIDOMXULElement : nsIDOMElement interface nsIDOMXULElement : nsIDOMElement
{ {
attribute DOMString id; attribute DOMString id;
@ -116,4 +116,8 @@ interface nsIDOMXULElement : nsIDOMElement
nsIDOMNodeList getElementsByAttribute(in DOMString name, nsIDOMNodeList getElementsByAttribute(in DOMString name,
in DOMString value); in DOMString value);
nsIDOMNodeList getElementsByAttributeNS(in DOMString namespaceURI,
in DOMString name,
in DOMString value);
}; };