2017-05-04 3 views
0

Je rencontre un problème lors de la comparaison de divers éléments de mon document XML avec XMLUnit (2.2.1). Dans mon document il y a plusieurs éléments xml et je veux savoir, s'ils diffèrent les uns des autres. Cependant, je ne veux pas comparer tous les éléments xml de la même manière. Parfois, je veux juste les comparer par leur nom. Dans d'autres cas, je veux les comparer par nom et attribut ou par nom et texte.Unité XML - Utilisation de sélecteurs d'éléments personnalisés sur différents éléments xml

Voici un exemple (voir les commentaires)

contrôle

<?xml version="1.0" encoding="UTF-8"?> 
<ROOT> 
    <LANGUAGES> 
     <!-- Compare LANGUAGE by Name and Attribute --> 
     <LANGUAGE VALUE="DE" /> 
     <LANGUAGE VALUE="EN" /> 
     <LANGUAGE VALUE="IT" /> 
     <LANGUAGE VALUE="FR" /> 
    </LANGUAGES> 
    <CODES> 
     <!-- Compare CODE by Name and Text --> 
     <CODE>10000-1</CODE> 
     <CODE>20000-2</CODE> 
     <CODE>30000-3</CODE> 
     <CODE>40000-4</CODE> 
    </CODES> 
    <CONTACT> <!-- Compare CONTACT and Children just by Name --> 
     <FIRSTNAME>Max</FIRSTNAME> 
     <SURNAME>Mustermann</SURNAME> 
    </CONTACT> 
</ROOT> 

Test:

<?xml version="1.0" encoding="UTF-8"?> 
<ROOT> 
    <LANGUAGES> 
     <!-- Compare LANGUAGE by Name and Attribute --> 
     <LANGUAGE VALUE="DE" /> 
     <LANGUAGE VALUE="FR" /> 
    </LANGUAGES> 
    <CODES> 
     <!-- Compare CODE by Name and Text --> 
     <CODE>20000-2</CODE> 
     <CODE>40000-4</CODE> 
    </CODES> 
    <CONTACT> <!-- Compare CONTACT and Children by Name --> 
     <FIRSTNAME>Tim</FIRSTNAME> 
     <SURNAME>Mustermann</SURNAME> 
    </CONTACT> 
</ROOT> 

J'ai essayé ElementSelectors en combinaison avec ElementSelectors.conditionalBuilder (https://github.com/xmlunit/user-guide/wiki/SelectingNodes#conditional-elementselectors) à appliquer seulement une ElementSelector sur un élément spécifique (whenElementIsNamed). Peut-être que ce n'est pas la bonne approche pour ce que je veux réaliser.

Ceci est mon code que j'utilise pour le test:

public void xmlDiff() { 
    String control = getControlDocument(); // 
    String test = getTestDocument(); // 
    Diff myDiff = DiffBuilder.compare(control)// 
      .withTest(test) // 
      .ignoreWhitespace() // 
      .ignoreComments() // 
      .checkForSimilar() // 
      .withNodeMatcher(new DefaultNodeMatcher(partialElementSelector("LANGUAGE", ElementSelectors.byNameAndAllAttributes), partialElementSelector("CODE",ElementSelectors.byNameAndText), ElementSelectors.byName)) // 
      .build(); 
    assertThat(myDiff.hasDifferences()).isTrue(); // 
} 

    private ElementSelector partialElementSelector(final String expectedName, final ElementSelector elementSelector) { 
     return ElementSelectors.conditionalBuilder().whenElementIsNamed(expectedName).thenUse(elementSelector).build(); 
    } 

Ce que je réellement besoin est l'information que deux langues (FR, IT) et deux codes (10000-1,30000-3) ont été supprimé (non remplacé) et FIRSTNAME modifié.

Comment puis-je obtenir ces informations, avec ou sans unité XML (DiffBuilder)?

Nous vous remercions de votre aide!

Répondre

0

Il existe une différence subtile entre l'utilisation de trois ElementSelector dans le constructeur de DefaultNodeMatcher et l'utilisation d'un seul ElementSelector avec plusieurs conditions.

Qu'est-ce que vous voulez atteindre avec les trois sélecteurs peut également être écrit comme

ElementSelectors.conditionalBuilder() 
    .whenElementIsNamed("LANGUAGE") 
    .thenUse(ElementSelectors.byNameAndAllAttributes) 
    .whenElementIsNamed("CODE") 
    .thenUse(ElementSelectors.byNameAndText) 
    .elseUse(ElementSelectors.byName) 
    .build(); 

À première vue, cela semble faire la même chose, mais il ne fonctionne pas. En fait, cela fonctionnera. Voici ce que je reçois de votre exemple:

Expected child nodelist length '4' but was '2' - comparing <LANGUAGES...> at /ROOT[1]/LANGUAGES[1] to <LANGUAGES...> at /ROOT[1]/LANGUAGES[1] (DIFFERENT) 
Expected child 'LANGUAGE' but was 'null' - comparing <LANGUAGE...> at /ROOT[1]/LANGUAGES[1]/LANGUAGE[2] to <NULL> (DIFFERENT) 
Expected child 'LANGUAGE' but was 'null' - comparing <LANGUAGE...> at /ROOT[1]/LANGUAGES[1]/LANGUAGE[3] to <NULL> (DIFFERENT) 
Expected child nodelist length '4' but was '2' - comparing <CODES...> at /ROOT[1]/CODES[1] to <CODES...> at /ROOT[1]/CODES[1] (DIFFERENT) 
Expected child 'CODE' but was 'null' - comparing <CODE...> at /ROOT[1]/CODES[1]/CODE[1] to <NULL> (DIFFERENT) 
Expected child 'CODE' but was 'null' - comparing <CODE...> at /ROOT[1]/CODES[1]/CODE[3] to <NULL> (DIFFERENT) 
Expected text value 'Max' but was 'Tim' - comparing <FIRSTNAME ...>Max</FIRSTNAME> at /ROOT[1]/CONTACT[1]/FIRSTNAME[1]/text()[1] to <FIRSTNAME ...>Tim</FIRSTNAME> at /ROOT[1]/CONTACT[1]/FIRSTNAME[1]/text()[1] (DIFFERENT) 

Voici donc ce qui se passe: Quand xmlunit regarde la LANGUAGE avec VALUEen la première ElementSelector conditionnelle que vous avez construit retournera false pour tous les candidats LANGUAGE éléments.

Lorsque vous utilisez le constructeur DefaultNodeMatcher multi-arg la prochaine ElementSelector sera demandé - qui sera également le retour false dans votre cas car il est seulement intéressé par CODE éléments. Et puis le troisième ElementSelector est consulté qui acceptera volontiers tout élément de test nommé LANGUAGE.

Lorsque vous utilisez le ElementSelector unique que j'ai mis en place au-dessus du sélecteur combiné ne consultera jamais l'une des solutions de rechange dès qu'un Predicate a retourné true. Cela signifie qu'il n'y aura pas de réflexions pour l'élément LANGUAGE une fois que le sélecteur est retourné false.

Je vais essayer de mettre à jour https://github.com/xmlunit/user-guide/wiki/SelectingNodes#nodematcher avec votre exemple et aimerais obtenir votre aide pour améliorer la documentation.

+0

Merci Stefan, c'est ce que je cherchais :)! – fwshngtn

+0

J'ai ajouté https://github.com/xmlunit/user-guide/wiki/SelectingNodes#using-more-than-one-elementselector-at-the-same-time –

+0

Heureux qu'il fonctionne pour vous @fwshngtn –