Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中从XSD创建Xpath_Java_Xpath_Xsd - Fatal编程技术网

在Java中从XSD创建Xpath

在Java中从XSD创建Xpath,java,xpath,xsd,Java,Xpath,Xsd,我使用ApacheXMLSchema框架来解析和获取XSD的元素。现在我需要将XPath字符串与这些元素中的每一个关联起来。有人能告诉我怎么做吗。是否有任何现有的算法或框架能够做到这一点 例如: <?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:simpleType name="stringtype">

我使用ApacheXMLSchema框架来解析和获取XSD的元素。现在我需要将XPath字符串与这些元素中的每一个关联起来。有人能告诉我怎么做吗。是否有任何现有的算法或框架能够做到这一点

例如:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:simpleType name="stringtype">
  <xs:restriction base="xs:string"/>
</xs:simpleType>

<xs:simpleType name="inttype">
  <xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>

<xs:simpleType name="dectype">
  <xs:restriction base="xs:decimal"/>
</xs:simpleType>

<xs:simpleType name="orderidtype">
  <xs:restriction base="xs:string">
    <xs:pattern value="[0-9]{6}"/>
  </xs:restriction>
</xs:simpleType>

<xs:complexType name="shiptotype">
  <xs:sequence>
    <xs:element name="name" type="stringtype"/>
    <xs:element name="address" type="stringtype"/>
    <xs:element name="city" type="stringtype"/>
    <xs:element name="country" type="stringtype"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="itemtype">
  <xs:sequence>
    <xs:element name="title" type="stringtype"/>
    <xs:element name="note" type="stringtype" minOccurs="0"/>
    <xs:element name="quantity" type="inttype"/>
    <xs:element name="price" type="dectype"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="shipordertype">
  <xs:sequence>
    <xs:element name="orderperson" type="stringtype"/>
    <xs:element name="shipto" type="shiptotype"/>
    <xs:element name="item" maxOccurs="unbounded" type="itemtype"/>
  </xs:sequence>
  <xs:attribute name="orderid" type="orderidtype" use="required"/>
</xs:complexType>

<xs:element name="shiporder" type="shipordertype"/>

</xs:schema>

对于你想要的东西,没有现成的解决方案;您必须使用访问者模式编写自己的。或者,如果这是一个为运行时使用而不是在运行时动态生成的设计时工件,则可以使用类似的解决方案

如果模式允许递归结构,或者如果它包含通配符,那么这是一个相当棘手的问题,您需要更精确地指定您的需求。对于相对简单的非递归模式,它应该简单得多,尽管您需要提供额外的信息,例如根元素名是什么。

阅读一些行间的内容,我试图回答这个问题。您可以看一看在Java中使用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);
    }
}
导入java.io.File;
导入java.util.HashMap;
导入java.util.Map;
导入java.util.Stack;
导入javax.xml.parsers.*;
导入org.xml.sax.*;
导入org.xml.sax.helpers.DefaultHandler;
/**
*SAX处理程序,为遇到的每个元素创建和打印XPath表达式。
*
*如果元素出现在层次结构的不同级别上,则该算法并非绝对正确。
*下面是一个例子:
* - 
* - 
* - 
* - 
* - 
* -     
* - 
*
*将报告
*
*//elemA[0]
*//埃莱玛[1]
*//elemB[0]
*//埃莱玛[2]
*//elemC[0]
*//elemC[0]/elemB[1](这是错误的:应该是//elemC[0]/elemB[0])
*
*它还忽略名称空间,因此将其视为。
*/
公共类SAXCreateXPath扩展了DefaultHandler{
//所有遇到的标记及其运行计数的映射
私有地图标记计数;
//跟踪元素的连续性
私有堆栈标签;
//设置为最近关闭的标记的标记名
字符串lastClosedTag;
/**
*构造XPath表达式
*/
私有字符串getCurrentXPath(){
字符串str=“/”;
布尔值优先=真;
用于(字符串标记:标记){
如果(第一)
str=str+tag;
其他的
str=str+“/”+标记;
str+=“[”+tagCount.get(tag)+“]”;
第一个=假;
}
返回str;
}
@凌驾
public void startDocument()引发异常{
标签=新堆栈();
tagCount=newhashmap();
}
@凌驾
public void startElement(字符串namespaceURI、字符串localName、字符串qName、属性atts)
抛出SAX异常
{
布尔值IsRepeateElement=false;
if(tagCount.get(localName)==null){
tagCount.put(localName,0);
}否则{
tagCount.put(localName,1+tagCount.get(localName));
}
if(lastClosedTag!=null){
//最近关闭了一个元素。。。
if(lastClosedTag.equals(localName)){
//…和现在的一样
isrepeateElement=true;
}否则{
//…但它与当前的不同,所以丢弃它
tags.pop();
}
}
//如果不是同一个元素,则将新元素和零计数添加到列表中
如果(!isRepeatElement){
tags.push(localName);
}
System.out.println(getCurrentXPath());
lastClosedTag=null;
}
@凌驾
public void endElement(字符串uri、字符串localName、字符串qName)引发SAXException{
//如果两个标签连续闭合(无中间开口标签),
//然后,关于嵌套较深的一个的信息将被丢弃
if(lastClosedTag!=null){
tags.pop();
}
lastClosedTag=localName;
}
公共静态void main(字符串[]args)引发异常{
如果(参数长度<1){
System.err.println(“用法:SAXCreateXPath”);
系统出口(1);
}
//创建一个JAXP SAXParserFactory并对其进行配置
SAXParserFactory spf=SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
设置验证(假);
//创建JAXP SAXParser
SAXParser SAXParser=spf.newSAXParser();
//获取封装的SAXXMLReader
XMLReader=saxParser.getXMLReader();
//设置XMLReader的ContentHandler
setContentHandler(新的SAXCreateXPath());
字符串文件名=args[0];
字符串路径=新文件(文件名).getAbsolutePath();
如果(File.separatorChar!='/')){
path=path.replace(File.separatorChar,“/”);
}
如果(!path.startsWith(“/”){
path=“/”+路径;
}
//告诉XMLReader解析XML文档
parse(“文件:”+path);
}
}
学分:

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