diff options
-rw-r--r-- | src/library/scala/xml/NodeSeq.scala | 44 | ||||
-rw-r--r-- | test/files/jvm/xml02.scala | 34 |
2 files changed, 68 insertions, 10 deletions
diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala index f5262a8ea3..e8198eea9c 100644 --- a/src/library/scala/xml/NodeSeq.scala +++ b/src/library/scala/xml/NodeSeq.scala @@ -50,7 +50,14 @@ abstract class NodeSeq extends Seq[Node] { /** Projection function. Similar to XPath, use <code>this \ "foo"</code> * to get a list of all elements of this sequence that are labelled with - * <code>"foo"</code>. Use <code>\ "_"</code> as a wildcard. + * <code>"foo"</code>. Use <code>\ "_"</code> as a wildcard. Use + * <code>ns \ "@foo"</code> to get the unprefixed attribute "foo". + * Use <code>ns \ "@{uri}foo"</code> to get the prefixed attribute + * "pre:foo" whose prefix "pre" is resolved to the namespace "uri". + * For attribute projections, the resulting NodeSeq attribute values are + * wrapped in a Group. + * There is no support for searching a prefixed attribute by + * its literal prefix. * The document order is preserved. * * @param that ... @@ -72,11 +79,27 @@ abstract class NodeSeq extends Seq[Node] { NodeSeq.fromSeq(zs.reverse) case _ if (that.charAt(0) == '@') && (this.length == 1) => - val k = that.substring(1) - val y = this(0) - y.attribute(k) match { - case Some(x) => Group(x) - case _ => NodeSeq.Empty + if (that.length() == 1) + throw new IllegalArgumentException(that) + if (that.charAt(1) == '{') { + val i = that.indexOf('}') + if (i == -1) + throw new IllegalArgumentException(that) + val (uri, key) = (that.substring(2,i), that.substring(i+1, that.length())) + if (uri == "" || key == "") + throw new IllegalArgumentException(that) + val y = this(0) + y.attribute(uri, key) match { + case Some(x) => Group(x) + case _ => NodeSeq.Empty + } + } else { + val k = that.substring(1) + val y = this(0) + y.attribute(k) match { + case Some(x) => Group(x) + case _ => NodeSeq.Empty + } } case _ => @@ -96,7 +119,14 @@ abstract class NodeSeq extends Seq[Node] { /** projection function. Similar to XPath, use <code>this \\ 'foo</code> * to get a list of all elements of this sequence that are labelled with - * <code>"foo"</code>. Use <code>\\ "_"</code> as a wildcard. + * <code>"foo"</code>. Use <code>\\ "_"</code> as a wildcard. Use + * <code>ns \\ "@foo"</code> to get the unprefixed attribute "foo". + * Use <code>ns \\ "@{uri}foo"</code> to get each prefixed attribute + * "pre:foo" whose prefix "pre" is resolved to the namespace "uri". + * For attribute projections, the resulting NodeSeq attribute values are + * wrapped in a Group. + * There is no support for searching a prefixed attribute by + * its literal prefix. * The document order is preserved. * * @param that ... diff --git a/test/files/jvm/xml02.scala b/test/files/jvm/xml02.scala index ad1e95cbb0..1c3f4c2599 100644 --- a/test/files/jvm/xml02.scala +++ b/test/files/jvm/xml02.scala @@ -5,11 +5,11 @@ object Test extends TestConsoleMain { import scala.xml.{NodeSeq, Utility} import NodeSeq.view - val ax = <hello foo="bar"> + val ax = <hello foo="bar" x:foo="baz" xmlns:x="the namespace from outer space"> <world/> </hello> - val cx = <z:hello foo="bar" xmlns:z="z"> + val cx = <z:hello foo="bar" xmlns:z="z" x:foo="baz" xmlns:x="the namespace from outer space"> crazy text world </z:hello> @@ -22,11 +22,38 @@ object Test extends TestConsoleMain { assertTrue("@two", ax \ "@foo" == xml.Text("bar")) // dto. assertTrue("@three", bx \ "@foo" == "bar&x") // dto. assertTrue ("@four", (bx \ "@foo") sameElements List(xml.Text("bar&x"))) - //assertTrue("@four", (bx \ "@foo") sameElements List(xml.Text("bar"),xml.EntityRef("amp"),xml.Text("x"))) assertEquals("@five", "<hello foo=\"bar&x\"></hello>", bx.toString) } } + object XmlEy extends TestCase("attributes with namespace") with Assert { + override def runTest = { + val z = ax \ "@{the namespace from outer space}foo" + assertTrue("@six", ax \ "@{the namespace from outer space}foo" == "baz") + assertTrue("@eight", cx \ "@{the namespace from outer space}foo" == "baz") + + try { + ax \ "@" + assertTrue("wrong1", false) + } catch { + case _: IllegalArgumentException => + } + try { + ax \ "@{" + assertTrue("wrong2", false) + } catch { + case _: IllegalArgumentException => + } + try { + ax \ "@{}" + assertTrue("wrong3", false) + } catch { + case _: IllegalArgumentException => + } + + } + } + object XmlPat extends TestCase("patterns") with Assert { override def runTest = { assertTrue(<hello/> match { case <hello/> => true; case _ => false; }) @@ -44,6 +71,7 @@ object Test extends TestConsoleMain { } def suite = new TestSuite( XmlEx, + XmlEy, XmlPat, DodgyNamespace ) |