如何读取complexType中的XSD元素?在JAVA

时间:2013-09-18 09:51:09

标签: xml xpath xsd

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()); 
    }
}
}

感谢您的建议。

2 个答案:

答案 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);
    }
}