【问题标题】:How can I read in XSD elements in complexType? in JAVA如何读取 complexType 中的 XSD 元素?在 JAVA 中
【发布时间】:2013-09-18 09:51:08
【问题描述】:

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>

我需要读取带有 name="Detail_begin" 和 name="MASK" 的所有元素的 complexType。 在 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()); 
    }
}
}

感谢您的建议。

【问题讨论】:

    标签: xml xpath xsd


    【解决方案1】:

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

    【讨论】:

    • 你能给我写更多关于它的信息或者给我写一些例子吗?谢谢
    • 其实就是这个例子。它为您提供标记名为“xsd:complexType”和名称为“Detail_begin”或“MASK”的所有元素。我不知道如何在 java 中评估 xpath,如果这是你想知道的
    • 我是 Java 初学者。如果我想用 xpath 将所有元素打印到屏幕上,你能写示例代码吗?谢谢
    • 好的,但是当我运行此代码时,for 循环中仍然有 result.getLength()=0。
    • 是的,问题出在哪里?
    【解决方案2】:

    您可以考虑扩展 xsd 解析的 SAX 解析实现以生成 Xpaths

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-24
      • 1970-01-01
      • 2019-07-28
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      相关资源
      最近更新 更多