2016-02-23 4 views
1

J'essaie actuellement de générer un ensemble de modèles (spécifié via XML). Pour ce faire, je dois changer un seul attribut dans le fichier et l'enregistrer sous un nouveau nom de fichier.Modifier le fichier XML avec SAX

Le fichier ressemble à XML ceci:

(...) 
<place id="P19" initialMarking="0" invariant="&lt; inf" markingOffsetX="0.0" markingOffsetY="0.0" name="P19" nameOffsetX="-5.0" nameOffsetY="35.0" positionX="615.0" positionY="375.0"/> 
<place id="P20" initialMarking="0" invariant="&lt; inf" markingOffsetX="0.0" markingOffsetY="0.0" name="P20" nameOffsetX="-5.0" nameOffsetY="35.0" positionX="375.0" positionY="225.0"/> 
(...) 

Ce qui doit changer est la valeur de initialMarking aux valeurs de 2 à 999.

Voici ce que j'ai jusqu'à présent: C'est là que je obtenir la liste des fichiers à modifier et de les transmettre à l'analyseur

public void parse(String dir){ 
     getFiles(dir); 

     try { 
      XMLReader xmlReader = XMLReaderFactory.createXMLReader(); 

      for(int i = 0; i < fileList.length; i++) { 
       FileReader reader = new FileReader(fileList[i]); 
       InputSource inputSource = new InputSource(reader); 
       xmlReader.setContentHandler(new ModelContentHandler()); 
       xmlReader.parse(inputSource); 
      } 
(...) 

C'est là que je suis à la recherche de l'élément que je dois changer:

public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { 
     if(localName.equals("place") && atts.getValue(0).equals("P14") && atts.getValue(1).equals("2")){ 
      System.out.println("Initial Marking of " + atts.getValue(0) + " is: " + atts.getValue(1) + "\n"); 
      while(currentTokens <= Configuration.MAX_TOKENS){ 
       System.out.println("Setting initial Tokens to: " + currentTokens); 

      } 
     } 
    } 

Maintenant, au lieu d'imprimer « Configuration ... » Je voudrais changer la valeur en fonction et juste enregistrer le fichier entier sous un nouveau nom comme « Model_X_Y_Token.xml ».

Cela semble être une chose assez simple à faire, mais je n'ai jamais utilisé SAX auparavant et en regardant le JavaDoc, je n'arrive même pas à trouver un endroit pour commencer. Peut-être que quelqu'un peut me diriger dans la bonne direction?

+0

est SAX une exigence? DOM serait beaucoup plus facile à coder avec –

Répondre

1

L'une des meilleures approches ici est d'utiliser dom4j. Je ne comprends pas exactement la grande image de ce que vous essayez de faire, mais je comprends le résultat que vous voulez obtenir. Notez que vous aurez également besoin de jaxen pour cela.

Étape 1: lire le fichier dans un xml doxument

for(int i=0; i<fileList.length; i++){ 
     Document doc = new SAXReader().read(fileList[i]); 
    } 

Etape 2: analyser les éléments dont vous avez besoin. Pour cela, vous devez connaître un peu de xpath. // /place va chercher tous les éléments de l'endroit. ///place [@ id = "P14"] va chercher seulement un élément de lieu.

Element place14 = (Element) doc.selectSingleNode("//*/place[@id="p14" and initialMarking="2"]"); 

Etape 3:. Modifier les attributs de l'élément

plac14.attribute ("attributename") setValue ("attributeValue");

+0

Merci pour la réponse. J'ai quelques problèmes pour implémenter votre suggestion. 1. L'instruction XPath semble incorrecte. L'élément-objet est toujours vide. J'ai changé la chaîne en '// place [@ id =" P14 "] | // place [@ initialMarking = "2"] 'après avoir regardé dans XPath. En utilisant http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm, j'ai correctement identifié le nœud dans mon document. La méthode selectSingleNode ne produit pas et de nouveau un objet Element contenant "null". De même, après avoir modifié l'attribut, comment puis-je enregistrer le document sous un nouveau nom? L'objet Document n'a pas de méthode pour cela. – DCH

+0

Pour le réduire, j'ai modifié l'instruction XPath pour sélectionner uniquement un nœud qui a '" // place [@initialMarking = \ '2 \'] "'. Le selectSingleNode renvoie également simplement "null" dans ce cas. – DCH

+0

Après d'autres investigations, cela semble être un problème d'espace de noms.Il y a une ligne 'xmlns =" ​​http://www.informatik.hu-berlin.de/top/pnml/ptNetb "' dans mon fichier XML. Si j'enlève ça, ça fonctionne. Malheureusement, je dois le faire fonctionner avec l'espace de noms. – DCH

0

La façon la plus efficace possible est avec vtd-xml car il est la seule API qui fait quelque chose appelé la mise à jour incrémentale ...

import com.ximpleware.*; 

public class changeAttrVal { 
    public static void main(String s[]) throws VTDException,java.io.UnsupportedEncodingException,java.io.IOException{ 
     VTDGen vg = new VTDGen(); 
     if (!vg.parseFile("input.xml", false)) 
      return; 
     VTDNav vn = vg.getNav(); 
     AutoPilot ap = new AutoPilot(vn); 
     XMLModifier xm = new XMLModifier(vn); 
     ap.selectXPath("/*/place[@id=\"p14\" and @initialMarking=\"2\"]/@initialMarking"); 
     int i=0; 
     while((i=ap.evalXPath())!=-1){ 
      xm.updateToken(i+1, "499");// change initial marking from 2 to 499 
     } 
     xm.output("new.xml"); // output to a new document called new.xml 
    } 

} 
+0

Merci pour votre réponse. Je viens d'essayer vtd-xml et je rencontre des problèmes. Avec votre exemple de code, le fichier d'entrée est seulement enregistré tel quel, sous le nom "new.xml". Les modifications ne fonctionnent pas. Aussi, j'ai modifié votre exemple, puisque je veux un nouveau fichier pour chaque changement de "marquage initial", donc je reçois quelque chose comme "new 2 tokens.xml", "new 3 tokens.xml" et ainsi de suite. J'ai donc déplacé le xm.output dans la boucle while en tant que: xm.output ("new" + i + ".xml") ;. Cela ne fonctionne pas du tout, aucun fichier n'est sauvegardé. – DCH

+0

la sortie est identique à inplut car le xpath n'évalue rien à quoi que ce soit ... donc il n'y a pas de changement ... quelle serait la bonne expression xpath pour votre application loigc? –

+0

btw, dom4j est un chien, voici un article sur ce sujet http://sdiwc.net/digital-library/web-admin/upload-pdf/00000466.pdf –