这是一些基本的 xml 文档:
<h1>My Heading</h1>
<p align = "center"> My paragraph
<img src="smiley.gif" alt="Smiley face" height="42" width="42"></img>
<img src="sad.gif" alt="Sad face" height="45" width="45"></img>
<img src="funny.gif" alt="Funny face" height="48" width="48"></img>
</p>
<p>My para</p>
我想做的是找到元素,他的所有属性并保存每个元素的属性名称+属性值。到目前为止,这是我的代码:
private Map <String, String> tag = new HashMap <String,String> ();
public Map <String, String> findElement () {
try {
FileReader fRead = new FileReader (sourcePage);
BufferedReader bRead = new BufferedReader (fRead);
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance ();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder ();
Document doc = docBuilder.parse(new FileInputStream (new File (sourcePage)));
XPathFactory xFactory = XPathFactory.newInstance ();
XPath xPath = xFactory.newXPath ();
NodeList nl = (NodeList) xPath.evaluate("//img/@*", doc, XPathConstants.NODESET);
for( int i=0; i<nl.getLength (); i++) {
Attr attr = (Attr) nl.item(i);
String name = attr.getName();
String value = attr.getValue();
tag.put (name,value);
}
bRead.close ();
fRead.close ();
}
catch (Exception e) {
e.printStackTrace();
System.err.println ("An error has occured.");
}
当我寻找 img 的属性时出现问题,因为属性相同。 HashMap 不适合这样做,因为它会用相同的键覆盖值。也许我使用了错误的表达式来查找所有属性。还有其他方法如何获取第 n 个 img 元素的属性名称和值吗?
最佳答案
首先,让我们稍微平整一下 field 。我稍微清理了你的代码以获得编译起点。我删除了不必要的代码,并通过我对它应该做什么的最佳猜测来修复该方法。我对它进行了一些泛化,让它接受一个 tagName
范围。它仍然是相同的代码并且犯了相同的错误,但现在它可以编译(为了方便使用了 Java 7 功能,如果需要,可以将其切换回 Java 6)。我还拆分了try-catch
只是为了它而分成多个 block :
public Map<String, String> getElementAttributesByTagName(String tagName) {
Document document;
try (InputStream input = new FileInputStream(sourcePage)) {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
document = docBuilder.parse(input);
} catch (IOException | ParserConfigurationException | SAXException e) {
throw new RuntimeException(e);
}
NodeList attributeList;
try {
XPath xPath = XPathFactory.newInstance().newXPath();
attributeList = (NodeList)xPath.evaluate("//descendant::" + tagName + "[1]/@*", document, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
throw new RuntimeException(e);
}
Map<String, String> tagInfo = new HashMap<>();
for (int i = 0; i < attributeList.getLength(); i++) {
Attr attribute = (Attr)attributeList.item(i);
tagInfo.put(attribute.getName(), attribute.getValue());
}
return tagInfo;
}
当针对上面的示例代码运行时,它返回:
{height=48, alt=Funny face, width=48, src=funny.gif}
<小时/>
解决方案取决于您的预期输出。你要么想要
- 仅获取
<img>
之一的属性元素(比如第一个) - 获取所有
<img>
的列表元素及其属性
对于第一个解决方案,只需将 XPath 表达式更改为
//descendant::img[1]/@*
或
//descendant::" + tagName + "[1]/@*
与 tagName
范围。请注意,这与 //img[1]/@*
不同。即使在这种特殊情况下它返回相同的元素。
当以这种方式更改时,该方法返回:
{height=42, alt=Smiley face, width=42, src=smiley.gif}
正确返回第一个 <img>
的属性元素。
请注意,您甚至不必使用 XPath 表达式来完成此类工作。这是非 XPath 版本:
public Map<String, String> getElementAttributesByTagNameNoXPath(String tagName) {
Document document;
try (InputStream input = new FileInputStream(sourcePage)) {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
document = docBuilder.parse(input);
} catch (IOException | ParserConfigurationException | SAXException e) {
throw new RuntimeException(e);
}
Node node = document.getElementsByTagName(tagName).item(0);
NamedNodeMap attributeMap = node.getAttributes();
Map<String, String> tagInfo = new HashMap<>();
for (int i = 0; i < attributeMap.getLength(); i++) {
Node attribute = attributeMap.item(i);
tagInfo.put(attribute.getNodeName(), attribute.getNodeValue());
}
return tagInfo;
}
<小时/>
第二个解决方案需要稍微改变一下。我们想要返回所有 <img>
的属性文档中的元素。多个元素意味着我们将使用 List
它将容纳多个 Map<String, String>
实例,其中每个 Map
代表一<img>
元素。
完整的 XPath 版本,以防您实际需要一些复杂的 XPath 表达式:
public List<Map<String, String>> getElementsAttributesByTagName(String tagName) {
Document document;
try (InputStream input = new FileInputStream(sourcePage)) {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
document = docBuilder.parse(input);
} catch (IOException | ParserConfigurationException | SAXException e) {
throw new RuntimeException(e);
}
NodeList nodeList;
try {
XPath xPath = XPathFactory.newInstance().newXPath();
nodeList = (NodeList)xPath.evaluate("//" + tagName, document, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
throw new RuntimeException(e);
}
List<Map<String, String>> tagInfoList = new ArrayList<>();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
NamedNodeMap attributeMap = node.getAttributes();
Map<String, String> tagInfo = new HashMap<>();
for (int j = 0; j < attributeMap.getLength(); j++) {
Node attribute = attributeMap.item(j);
tagInfo.put(attribute.getNodeName(), attribute.getNodeValue());
}
tagInfoList.add(tagInfo);
}
return tagInfoList;
}
要去掉 XPath 部分,只需将其切换为单行:
NodeList nodeList = document.getElementsByTagName(tagName);
这两个版本,当针对上面的测试用例运行 "img"
时参数,返回:(为了清晰起见,格式化)
[ {height=42, alt=Smiley face, width=42, src=smiley.gif},
{height=45, alt=Sad face, width=45, src=sad.gif },
{height=48, alt=Funny face, width=48, src=funny.gif } ]
这是所有 <img>
的正确列表元素。
关于java - 如何分别获取每个元素的所有属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19136426/