Generare/ottengo xpath dal nodo XML java

Mi interessa consigli/pseudocodice codice/spiegazione piuttosto che l’effettiva attuazione.

  • Vorrei andare attraverso documento xml, tutti i suoi nodi
  • Controllare il nodo attributo esistenza

Caso se il nodo non ha l’attributo, get/generate String with value of its xpath
Caso se il nodo non hanno gli attributi, scorrere trogolo lista di attributi e creare xpath per ogni attributo del nodo così.

Parola di consigli? Speriamo che si forniscono alcune utili intel

EDIT:

Ragione per fare questo è .. sto scrivendo test automatici in jmeter, quindi per ogni richiesta è necessario verificare che la richiesta è in realtà ha fatto il suo lavoro, quindi sto affermando risultati da raggiungere nodi valori con xpath.(informazioni supplementari, irrilevante)

Quando la richiesta è piccola la sua non è problema di creare afferma a mano, ma per quelli più grandi e la sua davvero un dolore .. (extra info irrilevante)

BOUNTY :

Sto cercando java approccio

Obiettivo

Il mio obiettivo è quello di conseguire in seguito da questo ex file xml :

<root>
    <elemA>one</elemA>
    <elemA attribute1='first' attribute2='second'>two</elemA>
    <elemB>three</elemB>
    <elemA>four</elemA>
    <elemC>
        <elemB>five</elemB>
    </elemC>
</root>

per produrre il seguente :

//root[1]/elemA[1]='one'
//root[1]/elemA[2]='two'
//root[1]/elemA[2][@attribute1='first']
//root[1]/elemA[2][@attribute2='second']
//root[1]/elemB[1]='three'
//root[1]/elemA[3]='four'
//root[1]/elemC[1]/elemB[1]='five'

Spiegato :

  • Se il valore del nodo/di testo non è null/zero, ottenere xpath , add = ‘nodevalue’ per l’affermazione scopo
  • Se il nodo ha attributi per creare affermare, anche per loro,

BOUNTY AGGIORNAMENTO :

Ho trovato questo esempio, non produce i risultati corretti , ma sto cercando qualcosa di simile a questo:

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

  • Buona domanda, +1. Vedi la mia risposta per una completa XSLT 1.0 soluzione che prende come parametro una stringa che contiene un set di nodi e produce un’espressione XPath per ogni nodo in nodo-set. I nodi possono essere di qualsiasi tipo: documento-nodo, elemento, testo di un nodo, un attributo, un commento, PI, dello spazio dei nomi.
  • Che tipo di espressione XPath vuoi però? Si può semplicemente prendere l’indice di ogni elemento in suo genitore getChildren() nodelist e creare un xpath come /*[5]/*[2]/*[8]/@yourattr. Ma se vuoi far valere i risultati, non dovresti farlo in un altro modo? Scrivere un’espressione xpath che restituisce true se l’XML è corretto e false se non lo è, quindi valutarlo?
  • Voglio creare xpath dalla richiesta posso inviare(in modo che io possa usare per verificare i risultati), non l’altro senso intorno. Ho aggiornato la mia domanda
  • Ci sono buchi nella vostra aggiornati domanda. Che cosa succede se un elemento ha più di un nodo di testo come in: <x>text 1<y/>text 2</x> Come dovrebbe essere la voleva processo di soluzione qualsiasi elemento? Voglio aggiornare la mia risposta sia con XSLT e una soluzione a soluzione C# (la mia versione di Java è un po ‘ arrugginito) — questo sarà utile a voi?
  • Novatchev grazie per il commento, per quanto posso vedere che caso mai si verifica nel mio file xml, e non credo che lo farà. Come BalusC mi ha suggerito potrebbe far eseguire java XSLT, se produce l’output corretto come esempio che ho postato sopra. tnx
  • Che è bene sapere, grazie. Così, può essere utile se si mette questo chiarimento nella domanda stessa. Dal tuo ultimo commento, posso concludere che andando avanti con XSLT e possibilmente C# per la soluzione preziosa per te?
  • Novatchev sì sarebbe la maggior parte del benvenuto. Grazie
  • Ho prodotto una completa e molto breve (30 linee) XSLT soluzione che è facile da capire e risolve il tuo problema esattamente.
  • Ho aggiunto anche un passo-passo la spiegazione della soluzione. Grazie per il tuo apprezzamento.
  • Novatchev grazie davvero apprezzare
  • Grazie per il nuovo raffinatezza del problema. Sì, è stato facile per regolare la mia soluzione per affrontare il formato aggiornato. Ho aggiornato la mia risposta sia il codice che la spiegazione. Grazie per la fornitura di questo bel problema.
  • Possibile duplicato di come recuperare corrispondente xpath

InformationsquelleAutor ant | 2011-01-20

 

8 Replies
  1. 41

    Aggiornamento:

    @c0mrade ha aggiornato la sua domanda. Ecco una soluzione:

    Questa trasformazione XSLT:

    <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:variable name="vApos">'</xsl:variable>
    
        <xsl:template match="*[@* or not(*)] ">
          <xsl:if test="not(*)">
             <xsl:apply-templates select="ancestor-or-self::*" mode="path"/>
             <xsl:value-of select="concat('=',$vApos,.,$vApos)"/>
             <xsl:text>&#xA;</xsl:text>
            </xsl:if>
            <xsl:apply-templates select="@*|*"/>
        </xsl:template>
    
        <xsl:template match="*" mode="path">
            <xsl:value-of select="concat('/',name())"/>
            <xsl:variable name="vnumPrecSiblings" select=
             "count(preceding-sibling::*[name()=name(current())])"/>
            <xsl:if test="$vnumPrecSiblings">
                <xsl:value-of select="concat('[', $vnumPrecSiblings +1, ']')"/>
            </xsl:if>
        </xsl:template>
    
        <xsl:template match="@*">
            <xsl:apply-templates select="../ancestor-or-self::*" mode="path"/>
            <xsl:value-of select="concat('[@',name(), '=',$vApos,.,$vApos,']')"/>
            <xsl:text>&#xA;</xsl:text>
        </xsl:template>
    </xsl:stylesheet>

    quando applicato sul documento XML:

    <root>
        <elemA>one</elemA>
        <elemA attribute1='first' attribute2='second'>two</elemA>
        <elemB>three</elemB>
        <elemA>four</elemA>
        <elemC>
            <elemB>five</elemB>
        </elemC>
    </root>

    produce esattamente lo volevo, risultato corretto:

    /root/elemA='one'
    /root/elemA[2]='two'
    /root/elemA[2][@attribute1='first']
    /root/elemA[2][@attribute2='second']
    /root/elemB='three'
    /root/elemA[3]='four'
    /root/elemC/elemB='five'

    Quando viene applicato il nuovo documento da @c0mrade:

    <root>
        <elemX serial="kefw90234kf2esda9231">
            <id>89734</id>
        </elemX>
    </root>

    di nuovo il risultato corretto è prodotto:

    /root/elemX='89734'
    /root/elemX[@serial='kefw90234kf2esda9231']

    Spiegazione:

    • Solo gli elementi che non hanno figli, elementi o attributi sono abbinati e trattati.

    • Per qualsiasi elemento, se non si hanno figli-elementi del suo antenato-o self elementi sono trattati in un modo specifico, denominato 'path'. Quindi il "='theValue'" parte è uscita e quindi un NL carattere.

    • Tutti gli attributi della corrispondenza elemento vengono poi elaborati.

    • Infine, i modelli vengono applicati a tutti i bambini-elementi.

    • L’elaborazione di un elemento in 'path' modalità è semplice: Un / carattere e il nome dell’elemento sono uscita. Poi, se ci sono fratelli precedenti con lo stesso nome, un “[numPrecSiblings+1]` è uscita.

    • Elaborazione di attributi è semplice: il Primo ancestor-or-self:: elementi di suo padre sono trattati in 'path' modalità, l’ [attrName=attrValue] parte è uscita, seguita da un NL carattere.

    Nota:

    • Nomi che sono in uno spazio dei nomi vengono visualizzati senza alcun problema e, nella loro prima forma leggibile.

    • Per facilitare la leggibilità, un indice di [1] non viene mai visualizzato.


    Qui di seguito la mia prima risposta (può essere ignorato)

    Qui è un puro XSLT 1.0 soluzione:

    Di seguito è riportato un esempio di documento xml e un foglio di stile che prende un nodo-impostare il parametro e produce una espressione XPath valida per ogni membro di un nodo.

    foglio di stile (buildPath.xsl):


    <xsl:stylesheet version='1.0'
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    >
    
    <xsl:output method="text"/>
    <xsl:variable name="theParmNodes" select="//namespace::*[local-name() =
    'myNamespace']"/>
    <xsl:template match="/">
      <xsl:variable name="theResult">
        <xsl:for-each select="$theParmNodes">
        <xsl:variable name="theNode" select="."/>
        <xsl:for-each select="$theNode |
    $theNode/ancestor-or-self::node()[..]">
          <xsl:element name="slash">/</xsl:element>
          <xsl:choose>
            <xsl:when test="self::*">           
              <xsl:element name="nodeName">
                <xsl:value-of select="name()"/>
                <xsl:variable name="thisPosition" 
                    select="count(preceding-sibling::*[name(current()) = 
                            name()])"/>
                <xsl:variable name="numFollowing" 
                    select="count(following-sibling::*[name(current()) = 
                            name()])"/>
                <xsl:if test="$thisPosition + $numFollowing > 0">
                  <xsl:value-of select="concat('[', $thisPosition +
                                                               1, ']')"/>
                </xsl:if>
              </xsl:element>
            </xsl:when>
            <xsl:otherwise> <!-- This node is not an element -->
              <xsl:choose>
                <xsl:when test="count(. | ../@*) = count(../@*)">   
                <!-- Attribute -->
                  <xsl:element name="nodeName">
                    <xsl:value-of select="concat('@',name())"/>
                  </xsl:element>
                </xsl:when>     
                <xsl:when test="self::text()">  <!-- Text -->
                  <xsl:element name="nodeName">
                    <xsl:value-of select="'text()'"/>
                    <xsl:variable name="thisPosition" 
                              select="count(preceding-sibling::text())"/>
                    <xsl:variable name="numFollowing" 
                              select="count(following-sibling::text())"/>
                    <xsl:if test="$thisPosition + $numFollowing > 0">
                      <xsl:value-of select="concat('[', $thisPosition + 
                                                               1, ']')"/>
                    </xsl:if>
                  </xsl:element>
                </xsl:when>     
                <xsl:when test="self::processing-instruction()">
                <!-- Processing Instruction -->
                  <xsl:element name="nodeName">
                    <xsl:value-of select="'processing-instruction()'"/>
                    <xsl:variable name="thisPosition" 
                       select="count(preceding-sibling::processing-instruction())"/>
                    <xsl:variable name="numFollowing" 
                        select="count(following-sibling::processing-instruction())"/>
                    <xsl:if test="$thisPosition + $numFollowing > 0">
                      <xsl:value-of select="concat('[', $thisPosition + 
                                                                1, ']')"/>
                    </xsl:if>
                  </xsl:element>
                </xsl:when>     
                <xsl:when test="self::comment()">   <!-- Comment -->
                  <xsl:element name="nodeName">
                    <xsl:value-of select="'comment()'"/>
                    <xsl:variable name="thisPosition" 
                             select="count(preceding-sibling::comment())"/>
                    <xsl:variable name="numFollowing" 
                             select="count(following-sibling::comment())"/>
                    <xsl:if test="$thisPosition + $numFollowing > 0">
                      <xsl:value-of select="concat('[', $thisPosition + 
                                                                1, ']')"/>
                    </xsl:if>
                  </xsl:element>
                </xsl:when>     
                <!-- Namespace: -->
                <xsl:when test="count(. | ../namespace::*) = 
                                                   count(../namespace::*)">
    
                  <xsl:variable name="apos">'</xsl:variable>
                  <xsl:element name="nodeName">
                    <xsl:value-of select="concat('namespace::*', 
                    '[local-name() = ', $apos, local-name(), $apos, ']')"/>
    
                  </xsl:element>
                </xsl:when>     
              </xsl:choose>
            </xsl:otherwise>            
          </xsl:choose>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
     </xsl:variable>
     <xsl:value-of select="msxsl:node-set($theResult)"/>
    </xsl:template>
    </xsl:stylesheet>

    sorgente xml (buildPath.xml):


    <!-- top level Comment -->
    <root>
        <nodeA>textA</nodeA>
     <nodeA id="nodeA-2">
      <?myProc ?>
            xxxxxxxx
      <nodeB/>
            <nodeB xmlns:myNamespace="myTestNamespace">
      <!-- Comment within /root/nodeA[2]/nodeB[2] -->
       <nodeC/>
      <!-- 2nd Comment within /root/nodeA[2]/nodeB[2] -->
            </nodeB>
            yyyyyyy
      <nodeB/>
      <?myProc2 ?>
        </nodeA>
    </root>
    <!-- top level Comment -->

    Risultato:

    /root/nodeA[2]/nodeB[2]/namespace::*[local-name() = 'myNamespace']
    /root/nodeA[2]/nodeB[2]/nodeC/namespace::*[local-name() =
    'myNamespace']
    • Novatchev grazie per la tua risposta, ma sto cercando di java approccio, +1 per il tuo impegno
    • Basta far eseguire Java XSLT e raccogliere i suoi risultati?
    • Potrei farlo, ma questo non è esattamente quello che ho chiesto, e dato che non conosco questo codice sono più a suo agio con il codice posso aggiornare/modificare, ho aggiornato la mia domanda. tnx
    • Novatchev Grande funziona esattamente come voglio. Sono davvero impressionato dalla piccola dimensione del codice e che cosa fa. Guarda come si sa è modo intorno xsl/xml dovrò esplorare xsl sicuramente. Potete consigliarmi qualche utile web/book resources per me di andare attraverso? Già ho bookmarked il vostro blog, visto tonnellate di codice che non riesco mai ho bisogno di iniziare con le basi di lavoro il mio cammino verso la cima. Grande tnx ancora una volta, posso accettare bontà 21h, io quando il tempo scade. Grazie per l’aiuto
    • Sei il benvenuto. Sì, XSLT è un linguaggio molto potente. Per ulteriori risorse, per favore, date un’occhiata alla mia risposta ad un’altra domanda COSÌ: stackoverflow.com/questions/339930/…
    • Novatchev, si prega di vedere BOUNTY AGGIORNAMENTO II, ho aggiornato la mia domanda. Dopo l’analisi di grandi file xml ho notato questo, di nuovo, penso di non dare il giusto esempio nella mia domanda. È questo un grande cambiamento nel codice? Potete modificare a farlo funzionare con l’ultimo aggiornamento? Accetto il bounty in un senso o nell’5 ore quando sono in grado di.
    • Novatchev assolutamente incredibile, grazie un milione. Funziona esattamente come avevo pianificato. Ho sicuramente bisogno di andare attraverso link che hai suggerito. grazie

  2. 14

    Qui è come questo può essere fatto con SAX:

    import java.util.HashMap;
    import java.util.Map;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.XMLReader;
    import org.xml.sax.helpers.DefaultHandler;
    
    public class FragmentContentHandler extends DefaultHandler {
    
        private String xPath = "/";
        private XMLReader xmlReader;
        private FragmentContentHandler parent;
        private StringBuilder characters = new StringBuilder();
        private Map<String, Integer> elementNameCount = new HashMap<String, Integer>();
    
        public FragmentContentHandler(XMLReader xmlReader) {
            this.xmlReader = xmlReader;
        }
    
        private FragmentContentHandler(String xPath, XMLReader xmlReader, FragmentContentHandler parent) {
            this(xmlReader);
            this.xPath = xPath;
            this.parent = parent;
        }
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
            Integer count = elementNameCount.get(qName);
            if(null == count) {
                count = 1;
            } else {
                count++;
            }
            elementNameCount.put(qName, count);
            String childXPath = xPath + "/" + qName + "[" + count + "]";
    
            int attsLength = atts.getLength();
            for(int x=0; x<attsLength; x++) {
                System.out.println(childXPath + "[@" + atts.getQName(x) + "='" + atts.getValue(x) + ']');
            }
    
            FragmentContentHandler child = new FragmentContentHandler(childXPath, xmlReader, this);
            xmlReader.setContentHandler(child);
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            String value = characters.toString().trim();
            if(value.length() > 0) {
                System.out.println(xPath + "='" + characters.toString() + "'");
            }
            xmlReader.setContentHandler(parent);
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            characters.append(ch, start, length);
        }
    
    }

    Può essere testato con:

    import java.io.FileInputStream;
    
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    import org.xml.sax.InputSource;
    import org.xml.sax.XMLReader;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();
    
            xr.setContentHandler(new FragmentContentHandler(xr));
            xr.parse(new InputSource(new FileInputStream("input.xml")));
        }
    }

    Questo consentirà di produrre l’output desiderato:

    //root[1]/elemA[1]='one'
    //root[1]/elemA[2][@attribute1='first]
    //root[1]/elemA[2][@attribute2='second]
    //root[1]/elemA[2]='two'
    //root[1]/elemB[1]='three'
    //root[1]/elemA[3]='four'
    //root[1]/elemC[1]/elemB[1]='five'
    • Bella 🙂 Tutti abbiamo bisogno ora è una StAX attuazione e avremo il set completo.
    • +1 per il vostro sforzo, secondo I biziclop commento, qualcuno potrebbe trovare ad essere utile in futuro
    • Attendere un minuto… elementNameCount conta le occorrenze di un particolare tipo di elemento (nome) a livello globale, attraverso il documento, a prescindere dal fatto che siano fratelli, sorelle, cugini (stesso livello, ma padre diverso), o su diversi livelli. Ma è uscita XPath "[" + count + "]" come se contiamo posizione tra fratelli e sorelle. Questo chiaramente non riuscire per non banale documenti. Giusto? E. g. <a><a>foo</a></a> sarebbe uscita //a[1]/a[2]='foo', e il [2] non è corretto.
    • Potete per favore hava occhiata a questa domanda – stackoverflow.com/questions/10698287/… . Sto usando le firme xml in java e per questo devo estrarre la parte che deve essere firmato dall’utilizzo di xpath. Ma semplicemente non funziona.
    • no non lo è, perché c’è un nuovo FragmentContentHandler creato in ogni startElement di transizione con proprio elementNameCount del registro di sistema. Questo dovrebbe funzionare correttamente, ma provare a me stesso.
    • Si può essere di destra. Non ho guardato questo in 3,5 anni. 🙂 Facci sapere se si prova.

  3. 12

    Con jOOX (un jquery API porta a Java, disclaimer – io lavoro per l’azienda dietro la biblioteca), si può quasi ottenere ciò che si desidera in una sola istruzione:

    //I'm assuming this:
    import static org.joox.JOOX.$;
    
    //And then...
    List<String> coolList = $(document).xpath("//*[not(*)]").map(
        context -> $(context).xpath() + "='" + $(context).text() + "'"
    );

    Se il documento è il documento di esempio:

    <root>
        <elemA>one</elemA>
        <elemA attribute1='first' attribute2='second'>two</elemA>
        <elemB>three</elemB>
        <elemA>four</elemA>
        <elemC>
            <elemB>five</elemB>
        </elemC>
    </root>

    Questo produrrà

    /root[1]/elemA[1]='one'
    /root[1]/elemA[2]='two'
    /root[1]/elemB[1]='three'
    /root[1]/elemA[3]='four'
    /root[1]/elemC[1]/elemB[1]='five'

    Da “quasi”, voglio dire che jOOX non (ancora) il supporto di corrispondenza/associazione di attributi. Quindi, i vostri attributi non produce alcun output. Questo sarà implementato in un prossimo futuro, però.

    • Potete per favore hava occhiata a questa domanda – stackoverflow.com/questions/10698287/… . Sto usando le firme xml in java e per questo devo estrarre la parte che deve essere firmato dall’utilizzo di xpath. Ma semplicemente non funziona
    • Mi dispiace, non ho alcuna esperienza con i “XPath trasformazione”. Non riconosco la libreria che stai usando non c’
    • che cosa è con il segno di dollaro $? Che legale Java?!
    • È un identificatore valido, sì. Statico-importato da JOOX.$. Io aggiornare la risposta
    • Questo funziona alla grande, ma non di grandi dimensioni in file XML. Qualche raccomandazione?
    • Si potrebbe implementare un SAX gestore

  4. 3
    private static void buildEntryList( List<String> entries, String parentXPath, Element parent ) {
        NamedNodeMap attrs = parent.getAttributes();
        for( int i = 0; i < attrs.getLength(); i++ ) {
            Attr attr = (Attr)attrs.item( i );
            //TODO: escape attr value
            entries.add( parentXPath+"[@"+attr.getName()+"='"+attr.getValue()+"']"); 
        }
        HashMap<String, Integer> nameMap = new HashMap<String, Integer>();
        NodeList children = parent.getChildNodes();
        for( int i = 0; i < children.getLength(); i++ ) {
            Node child = children.item( i );
            if( child instanceof Text ) {
                //TODO: escape child value
                entries.add( parentXPath+"='"+((Text)child).getData()+"'" );
            } else if( child instanceof Element ) {
                String childName = child.getNodeName();
                Integer nameCount = nameMap.get( childName );
                nameCount = nameCount == null ? 1 : nameCount + 1;
                nameMap.put( child.getNodeName(), nameCount );
                buildEntryList( entries, parentXPath+"/"+childName+"["+nameCount+"]", (Element)child);
            }
        }
    }
    
    public static List<String> getEntryList( Document doc ) {
        ArrayList<String> entries = new ArrayList<String>();
        Element root = doc.getDocumentElement();
        buildEntryList(entries, "/"+root.getNodeName()+"[1]", root );
        return entries;
    }

    Questo codice funziona con due ipotesi: non utilizzando gli spazi dei nomi e non ci sono mescolati elementi di contenuto. Lo spazio dei nomi limitazione non è grave, ma si potrebbe rendere la vostra espressione XPath molto più difficile da leggere, come ogni elemento dovrebbe essere qualcosa di simile a *:<name>[namespace-uri()='<nsuri>'][<index>], ma per il resto è facile da implementare. Contenuto misto d’altra parte sarebbe l’utilizzo di xpath molto noioso, in quanto dovresti essere in grado di trattano il secondo, il terzo e così via nodo di testo all’interno di un elemento.

    • +1 per il vostro sforzo, solo stax attuazione mancanti.
  5. 2
    1. uso del w3c.dom
    2. andare in modo ricorsivo fino
    3. per ogni nodo c’è un modo semplice per ottenere xpath: memorizzando come array, lista, mentre #2, o tramite la funzione che va in modo ricorsivo fino a quando il padre è null, quindi inverte array/lista incontrato i nodi.

    qualcosa di simile.

    AGG.:
    e concatenare lista finale per ottenere il finale di xpath.
    non credo che gli attributi sarà un problema.

  6. 1

    Ho fatto un compito simile una volta. L’idea principale utilizzato è che non è possibile utilizzare gli indici dell’elemento in xpath. Per esempio il seguente codice xml

    <root>
        <el />
        <something />
        <el />
    </root>

    xpath per la seconda <el/> sarà /root[1]/el[2] (xpath indici sono basati su 1). Questa legge come “prendere la prima radice, poi prendere la seconda da tutti gli elementi con il nome el”. Così elemento something non influenzano l’indicizzazione di elementi el. Così si può, in teoria, creare un xpath per ogni specifico elemento xml. In pratica ho realizzato questo camminando albero recursevely e ricordare le informazioni circa gli elementi e i loro indici lungo la strada.

    La creazione di xpath riferimento specifico attributo dell’elemento, quindi è stato solo l’aggiunta ‘/@attrName’ a dell’elemento xpath.

  7. 1

    Ho scritto un metodo per restituire il percorso assoluto di un elemento della Pratico XML biblioteca. Per darvi un’idea di come funziona, ecco un estratto forma uno dei unit test:

    assertEquals("/root/wargle[2]/zargle",
                 DomUtil.getAbsolutePath(child3a)); 

    Così, si potrebbe recurse attraverso il documento, si applicano i test, e utilizzare questo per tornare XPath. O, quello che è probabilmente il migliore, è che si potrebbe usare la XPath-a base di affermazioni dalla stessa biblioteca.

    • grazie per la tua risposta, la libreria dispone di alcuni documenti e/o esempi?
  8. 1

    Ho fatto esattamente la stessa cosa la scorsa settimana per il trattamento dei miei xml per solr in formato compatibile.

    Dal momento che si voleva un pseudo codice: in Questo modo ho realizzato che.

    //Si può saltare il riferimento a padre e figlio.

    1_ Inizializzare un nodo custom oggetto: NodeObjectVO {String nome nodo, String path, Elenco attr, NodeObjectVO padre, Elenco bambino}

    2_in Creare una lista vuota

    3_ Creare un dom rappresentazione di xml e l’iterazione thro il nodo. Per ogni nodo, ottenere le informazioni corrispondenti. Tutte le informazioni come il nome del Nodo,i nomi di attributo e valore devono essere prontamente disponibili da oggetto dom. ( È necessario controllare il dom NodeType, codice deve ignorare istruzione di elaborazione e testo normale nodi.)

    //Codice Bloat avviso.
    4_ L’unica parte difficile è ottenere il percorso. Ho creato un iterativo utilità metodo per ottenere la stringa xpath da NodeElement. (Mentre(nodo.Padre != null ) { path+=nodo.genitore.nodeName}.

    (È anche possibile raggiungere questo obiettivo attraverso il mantenimento di una globale percorso variabile, che tiene traccia del percorso principale per ogni iterazione.)

    5_ Nel metodo setter di setAttributes (Elenco), vorrei aggiungere il percorso dell’oggetto con tutti gli attributi disponibili. (un percorso con tutti gli attributi disponibili. Non un elenco di percorso con ogni possibile combinazione di attributi. Si potrebbe desiderare di fare someother modo. )

    6_ Aggiungere il NodeObjectVO alla lista.

    7_ Ora abbiamo un appartamento (non hierrarchial) elenco dei Nodi personalizzati Oggetti, che hanno tutte le informazioni di cui ho bisogno.

    (Nota: Come ho detto, ho mantenere la relazione genitore-figlio, probabilmente si dovrebbe saltare quella parte. C’è una possibilità del codice di gonfiore, soprattutto mentre getparentpath. Per le piccole xml questo non era un problema, ma questa è una preoccupazione per xml di grandi dimensioni).

Lascia un commento