2012-03-05 2 views
3

Я использую структуру Apache XMLSchema для синтаксического анализа и получения элементов XSD. Теперь мне нужно связать строку XPath с каждым из этих элементов. Может ли кто-нибудь дать какую-либо идею о том, как я могу это сделать. Любой существующий алгоритм или структура, которые это делают?Создание Xpath из XSD в Java

Пример:

<?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> 

XPath для

orderperson-> ./orderperson 
name-> ./shipto/name 

etc 

ответ

1

Там нет из раствора коробки для того, что вы хотите; вам придется писать свои собственные, используя шаблон посетителя. В качестве альтернативы, если это скорее артефакт времени разработки, который вы генерируете для использования во время выполнения, а не динамически во время выполнения, вы можете использовать решение, подобное этому SO post.

4

Если схема позволяет рекурсивные структуры или содержит подстановочные знаки, то это довольно сложная проблема, и вам нужно будет более точно указать свои требования. Для относительно простых нерекурсивных схем это должно быть гораздо более простым, хотя вам нужно будет предоставить дополнительную информацию, такую ​​как имя корневого элемента.

0

Чтение где-то между строками, я пытаюсь ответить на это. Вы можете посмотреть на JXPath, который позволяет использовать выражения XPath для пересечения графиков объектов в Java. У меня есть подозрение, что это то, чего вы пытаетесь достичь. Я могу ошибаться, хотя :)

1

Я думаю, что это может помочь:

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

Credits: http://www.coderanch.com/how-to/java/SAXCreateXPath

Смежные вопросы