XSD架构:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://www.xxx.sk/sirs"
elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sir="http://www.xxx.sk/sirs">
<xsd:complexType name="Detail_begin">
<xsd:sequence>
<xsd:element name="Block" type="xsd:int"></xsd:element>
<xsd:element name="Select" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="MASK">
<xsd:sequence>
<xsd:element name="Number_of_client" type="xsd:int"></xsd:element>
<xsd:element name="Indicator" type="xsd:string"></xsd:element>
<xsd:element name="Domicile" type="xsd:string"></xsd:element>
<xsd:element name="City" type="xsd:string"></xsd:element>
<xsd:element name="Sector" type="xsd:string"</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
我需要在complexType中读取name =“Detail_begin”和name =“MASK”的所有元素。 在XSD中是更复杂的类型。 哪种方式更容易? Xpath OR Node还是其他什么? 我试过这种方式:
public class XsdRead {
public static void main(String[] args) {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
Document xmlDocument = null;
try {
DocumentBuilder builder = builderFactory.newDocumentBuilder();
xmlDocument = builder.parse(new FileInputStream("xml/XmlSchema2.xsd"));
} catch (Exception e) {
e.printStackTrace();
}
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "//xsd:complexType[@name='Detail_begin' or @name='MASK']//xsd:element";
NodeList result = null;
try {
result = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
e.printStackTrace();
}
for (int i = 0; i < result.getLength(); i++) {
Element el = (Element)result.item(i);
System.out.println(el.getAttribute("name") + " = " + el.getNodeValue());
}
}
}
感谢您的建议。
答案 0 :(得分:0)
在xpath中应该很容易。可能是这样的:
//xsd:complexType[@name='Detail_begin' or @name='MASK']
我想在Java中你可以使用这样的东西:
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
Document xmlDocument = null;
try {
DocumentBuilder builder = builderFactory.newDocumentBuilder();
xmlDocument = builder.parse(new FileInputStream("xml/XmlSchema2.xsd"));
} catch (Exception e) {
//Errorhandling
}
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "//xsd:complexType[@name='Detail_begin' or @name='MASK']//xsd:element;
NodeList result = null;
try {
result= (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
} catch (Exception e) {
//Errorhandling
}
for(int i = 0; i < result.getLength(); i++)
{
Element e = (Element)result.item(i);
System.out.println(e.getAttribute("name") + " = " + e.getNodeValue();
}
答案 1 :(得分:0)
您可以考虑扩展xsd解析的SAX解析实现以生成Xpath
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
/**
* SAX handler that creates and prints XPath expressions for each element encountered.
*
* The algorithm is not infallible, if elements appear on different levels in the hierarchy.
* Something like the following is an example:
* - <elemA/>
* - <elemA/>
* - <elemB/>
* - <elemA/>
* - <elemC>
* - <elemB/>
* - </elemC>
*
* will report
*
* //elemA[0]
* //elemA[1]
* //elemB[0]
* //elemA[2]
* //elemC[0]
* //elemC[0]/elemB[1] (this is wrong: should be //elemC[0]/elemB[0] )
*
* It also ignores namespaces, and thus treats <foo:elemA> the same as <bar:elemA>.
*/
public class SAXCreateXPath extends DefaultHandler {
// map of all encountered tags and their running count
private Map<String, Integer> tagCount;
// keep track of the succession of elements
private Stack<String> tags;
// set to the tag name of the recently closed tag
String lastClosedTag;
/**
* Construct the XPath expression
*/
private String getCurrentXPath() {
String str = "//";
boolean first = true;
for (String tag : tags) {
if (first)
str = str + tag;
else
str = str + "/" + tag;
str += "["+tagCount.get(tag)+"]";
first = false;
}
return str;
}
@Override
public void startDocument() throws SAXException {
tags = new Stack();
tagCount = new HashMap<String, Integer>();
}
@Override
public void startElement (String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException
{
boolean isRepeatElement = false;
if (tagCount.get(localName) == null) {
tagCount.put(localName, 0);
} else {
tagCount.put(localName, 1 + tagCount.get(localName));
}
if (lastClosedTag != null) {
// an element was recently closed ...
if (lastClosedTag.equals(localName)) {
// ... and it's the same as the current one
isRepeatElement = true;
} else {
// ... but it's different from the current one, so discard it
tags.pop();
}
}
// if it's not the same element, add the new element and zero count to list
if (! isRepeatElement) {
tags.push(localName);
}
System.out.println(getCurrentXPath());
lastClosedTag = null;
}
@Override
public void endElement (String uri, String localName, String qName) throws SAXException {
// if two tags are closed in succession (without an intermediate opening tag),
// then the information about the deeper nested one is discarded
if (lastClosedTag != null) {
tags.pop();
}
lastClosedTag = localName;
}
public static void main (String[] args) throws Exception {
if (args.length < 1) {
System.err.println("Usage: SAXCreateXPath <file.xml>");
System.exit(1);
}
// Create a JAXP SAXParserFactory and configure it
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(false);
// Create a JAXP SAXParser
SAXParser saxParser = spf.newSAXParser();
// Get the encapsulated SAX XMLReader
XMLReader xmlReader = saxParser.getXMLReader();
// Set the ContentHandler of the XMLReader
xmlReader.setContentHandler(new SAXCreateXPath());
String filename = args[0];
String path = new File(filename).getAbsolutePath();
if (File.separatorChar != '/') {
path = path.replace(File.separatorChar, '/');
}
if (!path.startsWith("/")) {
path = "/" + path;
}
// Tell the XMLReader to parse the XML document
xmlReader.parse("file:"+path);
}
}