Hi,
I'm trying to evaluate an xpath expression on a given context (an xpath
previously evaluated, but don't know if/how this is possible.
Given the document
<html xmlns="
http://www.w3.org/1999/xhtml" xml:lang="en"><head/>
<body><div id="content"><div class="main">foo</div></div></body>
</html>
when I evaluate the xpath
"//body//div[@id='content']"
as context and afterwards evaluate the xpath
"//*[@class='main']/text()" using this context,
this fails with
RuntimeException: The local name 'xml:lang' is not valid for Xml 1.0
which indicates, that the 2nd xpath expression is run against the whole
document.
I know that I could prefix the 2nd xpath expression with the 1st one
(string concatenation), but I'd prefer not to do this.
Also this shows another issue: that xml:lang causes the error. If
there's a solution for that one it would also be great.
Here's the complete sample I'm running (with scales-jaxen 0.6.0-M1):
import scala.xml.Source
import nu.validator.htmlparser.common.XmlViolationPolicy
import nu.validator.htmlparser.sax.HtmlParser
import scales.utils.resources.SimpleUnboundedPool
import scales.utils.top
import scales.xml._
import scales.xml.ScalesXml._
import scales.xml.jaxen.ScalesXPath
import scales.xml.parser.sax.DefaultSaxSupport
object ScalesTest extends App {
val source = Source.fromString("""
<html xmlns="
http://www.w3.org/1999/xhtml"
xml:lang="en"><head/><body><div id="content"><div
class="main">foo</div></div></body></html>
""")
val doc = loadXmlReader(source, strategy = defaultPathOptimisation,
parsers = NuValidatorFactoryPool)
val root = top(doc)
// This works (prints "foo")
println(
ScalesXPath("//body//div[@id='content']//*[@class='main']/text()")
.withNameConversion(ScalesXPath.localOnly)
.evaluate(root).head.right.get.item.value
)
val ctxt = ScalesXPath("//body//div[@id='content']")
.withNameConversion(ScalesXPath.localOnly).xmlPaths(root).head
// Fails with
// Exception in thread "main" java.lang.RuntimeException: The local
name 'xml:lang' is not valid for Xml 1.0
println(
ScalesXPath("//*[@class='main']/text()")
.withNameConversion(ScalesXPath.localOnly)
.evaluate(ctxt).head.right.get.item.value
)
}
object NuValidatorFactoryPool extends
SimpleUnboundedPool[org.xml.sax.XMLReader] with DefaultSaxSupport {
def create = {
import nu.validator.htmlparser.{ sax, common }
import sax.HtmlParser
import common.XmlViolationPolicy
val reader = new HtmlParser
reader.setXmlPolicy(XmlViolationPolicy.ALLOW)
reader.setXmlnsPolicy(XmlViolationPolicy.ALLOW)
reader
}
}
TIA && cheers,
Martin