Java解析含自定义标签的XML:元素获取问题求助
Hey there! Let's work through this XML parsing problem together—sounds like you're stuck targeting specific nested elements and attributes, so let's break it down step by step. First, let's start with a sample XML structure that matches what you described (since you didn't share your actual XML, this will help ground the solutions):
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"> <bean id="primaryPool" class="com.example.ClusterPool"> <constructor-arg name="delegate"> <bean id="clusterDelegate" class="com.example.DelegateService" p:name="ProductionCluster" p:maximumClusters="8"/> </constructor-arg> <property name="displayName" value="Primary Cluster Pool"/> <property name="description" value="Manages high-availability cluster resources"/> <property name="clusterSize" value="4"/> </bean> <!-- Additional pool beans would go here --> </beans>
If you're looping through a poolList and not finding what you need, it's almost always a problem with node selection scope or XPath/query paths. For example:
- Are you starting your search from the root
<beans>node, or a nested child node that doesn't contain your target beans? - Are you filtering beans by a specific
classattribute (likeClusterPoolin the sample) to narrow down thepoolListto only relevant beans?
Let's use standard Java DOM parsing to walk through each value you need. This is straightforward and works for most XML parsing scenarios:
import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; public class XmlParser { public static void main(String[] args) throws Exception { Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new File("your-pool-config.xml")); doc.getDocumentElement().normalize(); // Get all pool beans (filter by class if needed) NodeList poolList = doc.getElementsByTagName("bean"); for (int i = 0; i < poolList.getLength(); i++) { Element poolBean = (Element) poolList.item(i); // 1. Get top-level bean id String beanId = poolBean.getAttribute("id"); System.out.println("Bean ID: " + beanId); // 2. Get delegate bean id + its p: attributes NodeList constructorArgs = poolBean.getElementsByTagName("constructor-arg"); for (int j = 0; j < constructorArgs.getLength(); j++) { Element arg = (Element) constructorArgs.item(j); if ("delegate".equals(arg.getAttribute("name"))) { Element delegateBean = (Element) arg.getElementsByTagName("bean").item(0); String delegateBeanId = delegateBean.getAttribute("id"); System.out.println("Delegate Bean ID: " + delegateBeanId); // Handle p: namespace attributes (use full namespace URI if needed) String pName = delegateBean.getAttribute("p:name"); String maxClusters = delegateBean.getAttribute("p:maximumClusters"); System.out.println("Delegate Name: " + pName); System.out.println("Max Clusters: " + maxClusters); break; // Exit once we find the delegate arg } } // 3. Get displayName, description, clusterSize String displayName = getPropertyValue(poolBean, "displayName"); String description = getPropertyValue(poolBean, "description"); String clusterSize = getPropertyValue(poolBean, "clusterSize"); System.out.println("Display Name: " + displayName); System.out.println("Description: " + description); System.out.println("Cluster Size: " + clusterSize); } } // Helper method to fetch property values cleanly private static String getPropertyValue(Element parent, String propName) { NodeList props = parent.getElementsByTagName("property"); for (int k = 0; k < props.getLength(); k++) { Element prop = (Element) props.item(k); if (propName.equals(prop.getAttribute("name"))) { return prop.getAttribute("value"); } } return "N/A"; // Or null if you prefer } }
If DOM traversal feels too verbose, XPath lets you target elements directly with query strings—this is especially useful for nested structures:
import org.w3c.dom.*; import javax.xml.xpath.*; import java.io.File; public class XPathXmlParser { public static void main(String[] args) throws Exception { Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new File("your-pool-config.xml")); XPath xpath = XPathFactory.newInstance().newXPath(); // Handle Spring's p namespace xpath.setNamespaceContext(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { return "p".equals(prefix) ? "http://www.springframework.org/schema/p" : null; } @Override public String getPrefix(String uri) { return null; } @Override public java.util.Iterator getPrefixes(String uri) { return null; } }); // Target all pool beans (adjust the class filter as needed) NodeList poolBeans = (NodeList) xpath.compile("//bean[@class='com.example.ClusterPool']") .evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < poolBeans.getLength(); i++) { Element poolBean = (Element) poolBeans.item(i); // Fetch all values with single XPath queries String beanId = xpath.compile("@id").evaluate(poolBean); String delegateBeanId = xpath.compile("constructor-arg[@name='delegate']/bean/@id").evaluate(poolBean); String pName = xpath.compile("constructor-arg[@name='delegate']/bean/@p:name").evaluate(poolBean); String maxClusters = xpath.compile("constructor-arg[@name='delegate']/bean/@p:maximumClusters").evaluate(poolBean); String displayName = xpath.compile("property[@name='displayName']/@value").evaluate(poolBean); String description = xpath.compile("property[@name='description']/@value").evaluate(poolBean); String clusterSize = xpath.compile("property[@name='clusterSize']/@value").evaluate(poolBean); // Print or process the values System.out.printf("Bean ID: %s%nDelegate ID: %s%nName: %s%nMax Clusters: %s%nDisplay Name: %s%nDescription: %s%nCluster Size: %s%n---%n", beanId, delegateBeanId, pName, maxClusters, displayName, description, clusterSize); } } }
- Missing p: attributes? Make sure your parser handles XML namespaces. In DOM, use
getAttributeNSwith the full Spring p namespace URI (http://www.springframework.org/schema/p) ifgetAttribute("p:name")fails. - No nodes found in poolList? Double-check that your initial node selection is starting from the root
<beans>element, and that you're not filtering out valid beans accidentally. - Nested bean not detected? Confirm that the
<bean>insideconstructor-argis a direct child node—if there's an extra wrapper element, adjust your XPath/traversal path accordingly.
内容的提问来源于stack exchange,提问作者John Fisherman

