简体   繁体   English

如何从 xsd 生成 xpath?

[英]How to generate xpath from xsd?

How can I generate xpath from an xsd?如何从 xsd 生成 xpath? XSD validates an xml. XSD 验证 xml。 I am working in a project where I am generating a sample XML from the xsd using java and then generating xpath from that XML. I am working in a project where I am generating a sample XML from the xsd using java and then generating xpath from that XML. If there is any way to generate xpath directly from xsd please let me know.如果有任何方法可以直接从 xsd 生成 xpath,请告诉我。

This might be of use:这可能有用:

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

There are a number of problems with such tools:此类工具存在许多问题:

The XPath expression generated rarely is a good one.很少生成的 XPath 表达式是一个很好的表达式。 No such tool will produce meaningful predicates beyond position information.除了 position 信息之外,没有这样的工具会产生有意义的谓词。

There is no tool (to my knowledge) that would generate an XPath expression that selects exactly a set of selected nodes.没有工具(据我所知)会生成一个 XPath 表达式,该表达式恰好选择一组选定的节点。

Apart from this, such tools used without learning XPath are really harmful -- they support ignorance.除此之外,没有学习XPath就使用这种工具确实有害-它们支持无知。

I would recommend serious learning of XPath using books and other resources such as following.我建议使用书籍和其他资源,例如以下资源,认真学习 XPath。

https://stackoverflow.com/questions/339930/any-good-xslt-tutorial-book-blog-site-online/341589#341589 https://stackoverflow.com/questions/339930/any-good-xslt-tutorial-book-blog-site-online/341589#341589

See the following answer for more information..有关更多信息,请参阅以下答案。

Is there an online tester for xPath selectors? 是否有 xPath 选择器的在线测试仪?

I've been working on a little library to do just this, though for larger and more complex schemas, there are issues you will need to address on a case-by-case basis (eg, filters for certain nodes).我一直在开发一个小型库来做到这一点,尽管对于更大和更复杂的模式,您需要根据具体情况解决一些问题(例如,某些节点的过滤器)。 See https://stackoverflow.com/a/45020739/3096687 for a description of the solution.有关解决方案的说明,请参阅https://stackoverflow.com/a/45020739/3096687

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM