IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

APIs XML Discussion :

batik : lire un fichier svg


Sujet :

APIs XML

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Octobre 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 15
    Points : 14
    Points
    14
    Par défaut batik : lire un fichier svg
    Bonjour à tous,

    J'ai récemment débuté dans l'utilisation de batik pour lire des images svg mais j'ai des soucis pour récupérer à l'intérieur une balise en particulier.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    package batik.test;
     
    import java.io.File;
    import java.io.IOException;
     
    import javax.xml.xpath.XPathExpressionException;
     
    import org.apache.batik.dom.AbstractDocument;
    import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
    import org.apache.batik.util.XMLResourceDescriptor;
    import org.w3c.dom.Document;
    import org.w3c.dom.Node;
    import org.w3c.dom.svg.SVGDocument;
    import org.w3c.dom.svg.SVGElement;
    import org.w3c.dom.xpath.XPathResult;
     
    public class CreateDocFromSVGFile {
     
    	public static void main(String[] args) throws XPathExpressionException {
     
    		try {
    		    String parser = XMLResourceDescriptor.getXMLParserClassName();
    		    SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
    		    File file = new File("C://SVGs_input//figure_text.svg");
    		    String uri = file.toURI().toString();
    		    Document doc = f.createDocument(uri);
    		    SVGDocument svgDocument = f.createSVGDocument(uri);
     
    		    AbstractDocument ab = (AbstractDocument) svgDocument;
    		    XPathNSResolver resolver = ab.createNSResolver(ab.getDocumentElement());
    		    XPathResult result = (XPathResult) ab.evaluate("//text", svgDocument.getDocumentElement(), resolver, XPathResult.ANY_TYPE, null);
    		    Node node = result.iterateNext();
    		    while (node != null) {
    		    	System.out.println("<" + node.getNodeName() + "> " + node.getTextContent());
    		    	node = result.iterateNext();
    		    }
     
    		} catch (IOException ex) {
    		    ex.printStackTrace();
    		}
    	}
     
    }

    L'expression "//*" me retourne bien toutes les balises mais dès que j'essaye autre chose de spécifique comme //title ou //text je n'obtiens rien du tout.

    Je sais que le problème vient du namespace par défaut (xmlns:"http://www.w3.org/2000/svg") et j'ai réussi en passant par jdom à obtenir ce que je voulais grâce à l'expression "//svg:text" mais cela ne marche pas avec batik.

    Je mets à disposition le fichier svg que l'on trouve sur la page de présentation de svg sur wikipédia :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?xml version="1.0" encoding="utf-8"?>
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300" height="200">
      <title>Exemple simple de figure SVG</title>
      <desc>Cette figure est constituée d'un rectangle, d'un segment de droite et d'un cercle.</desc>
     
      <rect width="100" height="80" x="0" y="70" fill="green" />
      <line x1="5" y1="5" x2="250" y2="95" stroke="red" />
      <circle cx="90" cy="80" r="50" fill="blue" />
       <text x="180" y="60">Un texte</text>
       <text x="180" y="60">Un autre texte</text>
    </svg>
    Et le résultat avec "//*" en expression :

    svg
    title
    desc
    rect
    line
    circle
    text
    text

    Merci d'avance

  2. #2
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Octobre 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2012
    Messages : 15
    Points : 14
    Points
    14
    Par défaut
    Bonjour à tous,

    Bon j'ai fini par trouver tout seul alors je mets la solution ici pour ceux qui pourrait en avoir besoin plus tard.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    package batik.test;
     
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Iterator;
     
    import javax.xml.namespace.NamespaceContext;
    import javax.xml.xpath.XPath;
    import javax.xml.xpath.XPathConstants;
    import javax.xml.xpath.XPathExpressionException;
    import javax.xml.xpath.XPathFactory;
     
    import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
    import org.apache.batik.util.XMLResourceDescriptor;
    import org.w3c.dom.Document;
    import org.w3c.dom.NodeList;
    import org.w3c.dom.svg.SVGDocument;
     
    public class ParseSVGWithBATIK {
     
    	private static String svgPath = "C://SVGs_input//figure_text.svg";
    	private static String svgNamespaceURI = "http://www.w3.org/2000/svg";
    	private static String newPrefix = "svg";
    	private static String query = "//desc";
     
    	public static void main(String[] args) {
     
    	    String parser = XMLResourceDescriptor.getXMLParserClassName();
    	    SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
    	    File file = new File(svgPath);
    	    String uri = file.toURI().toString();
    	    SVGDocument svgDocument = null;
    	    try {
    	        svgDocument = factory.createSVGDocument(uri);
    	    } catch (IOException e) {
    		e.printStackTrace();
    	    }
     
    	    NodeList nodes = getNodes(svgDocument);
    	    for (int i = 0; i < nodes.getLength(); i++) {
    	        if (nodes.item(i).getTextContent() != null && !nodes.item(i).getTextContent().isEmpty()) {
    			System.out.println("<" + nodes.item(i).getNodeName() + "> " + nodes.item(i).getTextContent());
    		} else if (nodes.item(i).getNodeValue() != null) {
    			System.out.println("<" + nodes.item(i).getNodeName() + "> " + nodes.item(i).getNodeValue());
    		} else {
    			System.out.println("<" + nodes.item(i).getNodeName() + ">");
    	        }
    	    }
    	}
     
    	/**
             * Executes XPath query over the SVG document.
             */
    	private static NodeList getNodes(Document document) {
    	    if (document != null) {
    	        try {
    		    return (NodeList) getXPath(document).evaluate(modifiedQuery(), document.getDocumentElement(), XPathConstants.NODESET);
    		} catch (XPathExpressionException e) {
    				throw new RuntimeException(e);
    		}
    	    }
    	    return null;
    	}
     
    	private static XPath getXPath(Document document) {
    		XPath xpath = XPathFactory.newInstance().newXPath();
    		xpath.setNamespaceContext(new NamespaceContext() {
    		    @Override
    		    public String getNamespaceURI(String prefix) {
    		        if (prefix.equals(newPrefix)) {
    			    return svgNamespaceURI;
    			}
    			return null;
    		    }
     
    		    @Override
    		    public String getPrefix(String namespaceURI) {
    			if (namespaceURI.equals(svgNamespaceURI)) {
    			    return newPrefix;
    			}
    			return null;
    		    }
     
    	            @Override
    		    public Iterator<?> getPrefixes(String namespaceURI) {
    			ArrayList<String> list = new ArrayList<String>();
    		        if (namespaceURI.equals(svgNamespaceURI)) {
    			    list.add(newPrefix);
    			}
    			return list.iterator();
    		    }
    		});
    		return xpath;
    	}
     
    	private static String modifiedQuery() {
    	    String doubleSlash = query.substring(0, 2);
    	    String tagName = query.substring(2, query.length());
                return doubleSlash + newPrefix + ":" + tagName;
    	}
     
    }

    Avec le résultat :

    <desc> Cette figure est constituée d'un rectangle, d'un segment de droite et d'un cercle.
    Je n'ai pas réussi à passer par la classe AbstractDocument de Batik, ça me trouve rien sauf quand je les retourne tous (//*). Je suis donc passé par la classe NamespaceContent qui sert a récupérer le prefix ou le NamespaceURI en fonction des besoins.
    Les déclarations de string en privé et la méthode modifiedQuery() sont pas vraiment nécessaires, c'était juste pour pas les avoir en dur.

    Y'a d'autres méthodes pour obtenir le même résultat, j'ai trouvé notamment ce lien très utile : http://www.edankert.com/defaultnamespaces.html


    Sur ce, bonne journée et bon code !

    FuRiOuZ

  3. #3
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    C'est une solution qui ne fait pas appeler Batik et c'est tout à fait bonne et valable.

    Si on veut le faire dans la piste de Batik, on peut sauver le code comme ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //...etc
    //c'est domage que cette ligne ne marche pas ou pas implémentée: ce serait idéale
    //XPathNSResolver resolver = ab.createNSResolver(ab.getDocumentElement());
    //le prefixe svg se peut choisi librement, c'est le uri qui est important
    XPathResult result = (XPathResult) ab.evaluate(
        "//svg:text",
        svgDocument.getDocumentElement(),
        new XPathNSResolver() {
            public String lookupNamespaceURI(String prefix) {
                if (prefix.equals("svg")) {
                    return "http://www.w3.org/2000/svg";
                } else {
                    return null;
                }
            }
        },
        XPathResult.ANY_TYPE,
        null
    );
    Node node = result.iterateNext();

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Batik] Lire un fichier SVG
    Par FuRiOuZ dans le forum Graphisme
    Réponses: 2
    Dernier message: 19/09/2013, 02h14
  2. [MFC] lire un fichier en int
    Par Kevgeii dans le forum MFC
    Réponses: 3
    Dernier message: 23/01/2004, 10h32
  3. Réponses: 5
    Dernier message: 11/01/2004, 21h17
  4. Lire un fichier de 50 gb
    Par Maryves dans le forum MFC
    Réponses: 2
    Dernier message: 08/01/2004, 15h08
  5. Lire le fichier du port série
    Par saibe dans le forum Linux
    Réponses: 7
    Dernier message: 09/04/2003, 10h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo