我正在研究用Java编写的解析器。我可以从各个位置接收带有各种内容的XML提要。我需要从feed中提取所有名称空间,根据feed调用this或that。我在使用Java获取此功能时遇到了一些麻烦,我不确定问题出在哪里。
让我们考虑一下这个XML:
<?xml version="1.0"?>
<?xml-stylesheet type='text/xsl' href='new.xsl'?>
<test xmlns:mynsone="http://www.ns.com/test" xmlns:demons="http://www.demons.com/test">
<p xmlns:domain="http://www.toto.com/test">
this is a test.
</p>
</test>
为了测试我的xPath表达式(我相当新),我写了一个应用于该XML的.xsl脚本:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output
method="html"
encoding="ISO-8859-1"
doctype-public="-//W3C//DTD XHTML//EN"
doctype-system="http://www.w3.org/TR/2001/REC-xhtml11-20010531"
indent="yes" />
<xsl:template match="/">
<xsl:for-each select="//namespace::*">
<xsl:value-of select="." />
<xsl:text> </xsl:text><br />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这正确地为我提供了迭代节点时遇到的命名空间列表:
http://www.w3.org/XML/1998/namespace
http://www.demons.com/test
http://www.ns.com/test
http://www.w3.org/XML/1998/namespace
http://www.demons.com/test
http://www.ns.com/test
http://www.toto.com/test
现在我回到Java:这是我使用的代码。
InputStream file = url.openStream();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "//namespace::*";
System.out.println(expression);
NodeList nodelist = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int k = 0; k < nodelist.getLength(); k++)
{
Node mynode = nodelist.item(k);
System.out.println(mynode.toString());
}
以下是我获得的结果:
xmlns:mynsone="http://www.ns.com/test"
org.apache.xml.dtm.ref.dom2dtm.DOM2DTMdefaultNamespaceDeclarationNode@7dbb8ca4
xmlns:domain="http://www.toto.com/test"
因此,不会返回“demons”命名空间。问题是,如果我在一个节点上放置几个名称空间,则只返回1个Java,而在XSL脚本上则显示所有名称空间。
我希望自己能够清醒自己;我花了几天的时间在网页上浏览一些例子,我不知道我是否真的很接近但只是遗漏了一些东西,或者我的表情根本就不合适......
提前致谢。
好的,所以我最终使用xPath 2.0来完成它,使用saxon-HE 9.4:
public static boolean detectGeoRssNamespace(InputStream sourceFeed) {
try {
if (sourceFeed.markSupported()) {
sourceFeed.reset();
}
String objectModel = NamespaceConstant.OBJECT_MODEL_SAXON;
System.setProperty("javax.xml.xpath.XPathFactory:"+NamespaceConstant.OBJECT_MODEL_SAXON, "net.sf.saxon.xpath.XPathFactoryImpl");
XPathFactory xpathFactory = XPathFactory.newInstance(objectModel);
XPath xpath = xpathFactory.newXPath();
InputSource is = new InputSource(sourceFeed);
SAXSource ss = new SAXSource(is);
NodeInfo doc = ((XPathEvaluator)xpath).setSource(ss);
String xpathExpressionStr = "distinct-values(//*[name()!=local-name()]/ concat('prefix=', substring-before(name(), ':'), '&uri=', namespace-uri()))";
XPathExpression xpathExpression = xpath.compile(xpathExpressionStr);
List nodelist = (List)xpathExpression.evaluate(doc, XPathConstants.NODESET);
System.out.println("<output>");
Iterator iter = nodelist.iterator();
while ( iter.hasNext() ) {
Object line = (Object)iter.next();
System.out.println(line.toString());
}
System.out.println("</output>");
} catch (XPathFactoryConfigurationException e) {
e.printStackTrace();
} catch (XPathException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
答案 0 :(得分:0)
如果将此命名空间提取到不同的xml元素,该怎么办?
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output
method="html"
encoding="ISO-8859-1"
doctype-public="-//W3C//DTD XHTML//EN"
doctype-system="http://www.w3.org/TR/2001/REC-xhtml11-20010531"
indent="yes" />
<xsl:template match="/">
<xsl:for-each select="//namespace::*">
<namespace>
<xsl:value-of select="." />
</namespace>
<xsl:text> </xsl:text><br />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
问题是使用xPath 2.0(包含在问题中的代码)解决的