2008-10-06 7 views
0

J'ai le problème que je ne peux pas sélectionner un nœud XML spécifique qui doit être supprimé. J'ai déjà essayé de sélectionner le noeud en utilisant le XPath qui fonctionne bien pour certains fichiers XML, mais je ne peux pas trouver le bon XPath pour un noeud dans un fichier plus complexe.Comment puis-je supprimer un nœud spécifique dans un fichier XML en utilisant vbscript

Est-ce que quelqu'un connaît un outil freeware qui peut charger un fichier XML pour que l'utilisateur puisse sélectionner un nœud spécifique et recevoir le XPath précis sans avoir une énumération dans le chemin?

/root/anything[2] < - Malheureusement, je ne peux pas utiliser une telle instruction car le numéro de l'élément peut changer. J'ai besoin d'une expression basée sur un attribut.

Dans le cas où il n'y a pas d'outil freeware pour cette opération, quelqu'un sait-il d'une autre façon comment je peux sélectionner le nœud nécessaire?

XML Exemple:

Noeud racine: SmsFormData

Attributs: xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: XSD = "http://www.w3.org/2001/XMLSchema" FormatVersion = "1.0" xmlns = "http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework"

de nœud enfant : Formulaire

Attributs: Id = "certains GUID" CustomData = "Certaines données" FormType = "un certain type" forceRefresh = "false"

enfant/nœud enfant: Pages

enfant/enfant/nœud enfant: page

Attributs: VendorId = "VendorName" id = "certains GUID" Assembly = "dll nom du fichier" Namespace = "certains namespace" type = "un certain type" HelpID = "">

Mon expression XPath pour sélectionner cette page spécifique serait maintenant:

xPath =/SmsFormData/Form/Pages/Page[@Id="some Guid"]

Pour la sélection, je suis en utilisant le code vbscript suivant:

Set objDOM = CreateObject("Msxml2.DOMDocument.4.0") 
objDOM.async = false    
objDOM.load(file)  
set objNode = objDOM.selectSingleNode(xPath) 

Le problème est maintenant que l'objet objNode est vide. Le noeud n'est pas sélectionné, mais pourquoi?

+0

Comment sur les échantillons du fichier XML avec lesquels vous essayez de travailler? – Kev

Répondre

2

Ceci est un problème d'espace de noms par défaut. Essayez d'inclure le code suivant après le chargement dans le fichier XML:

objDom.SetProperty "SelectionNamespaces", "xmlns:cf=""http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework""" 

Vous utilisez ensuite ce préfixe cf dans votre XPath par exemple:

objDom.SelectSingleNode("/cf:SmsFormData/cf:Form/cf:Pages/cf:Page[@Id='Some Guid']") 

Bien que cela puisse sembler un peu bizarre, il est un comportement intentionnel. Jetez un oeil à http://support.microsoft.com/kb/288147 pour plus d'informations, et vous pouvez trouver http://msdn.microsoft.com/en-us/library/ms950779.aspx utile aussi bien.

0

Étant donné le code XML suivant:

<root> 
    <anything foo="bar">value1</anything> 
    <anything foo="qux">value2</anything> 
</root> 

... vous pouvez obtenir la valeur du second noeud tout en utilisant l'expression XPath:

/root/anything[@foo="qux"] 

(donc, au lieu de l'index numéroté, vous utilisez @ property = "value" comme sélecteur).Comme un outil pour générer des requêtes de cette manière automagiquement, le Visual XPath bien nommé devrait faire l'affaire, et c'est gratuit (il vient même avec le code source C#).

Modifier, après un suivi par l'affiche: cette forme de sélection XPath fonctionne aussi bien pour les « cas simples » comme pour les documents les plus complexes. Vous faire doivent vous assurer que votre expression XPath est correcte, bien sûr, et bien que de Visual XPath sera en effet utiliser les index numériques, il vous donne au moins le reste de l'expression, et vous pouvez facilement remplacer la propriété @ = « valeur » sélecteur pour le numéro, et tester le résultat.

Compte tenu du XML exemple ci-dessus, ce VBscript:

objDOM.selectSingleNode("/root/anything[@foo=""qux""]/text()").nodeValue 

... retourne la chaîne « valeur2 »: en fonction de vos besoins, vous devrez peut-être modifier les choses un peu (encore une fois, des outils tels que Visual XPath, ou n'importe quel bon XPath reference vous aidera avec cela).

0

Merci pour votre réponse rapide! Cela fonctionne sûrement dans les cas simples, mais cela ne fonctionne pas dans mon cas précis :(

Alors laisse donc entrer dans les détails:

Noeud racine: SmsFormData

Attributs: xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = "http://www.w3.org/2001/XMLSchema" FormatVersion = "1.0" xmlns = "http: // schémas .microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework »

nœud enfant: Formulaire

Attributs: Id = "certains GUID" CustomData = "Certaines données" FormType = "un certain type" forceRefresh = "false"

enfant/nœud enfant: Pages

enfant/enfant/nœud enfant: page

Attributs: VendorId = "VendorName" id = "certains GUID" Comme semblée = "dll Nom du fichier" Namespace = "certains namespace" type = "un certain type" HelpID = "">

Mon expression XPath pour sélectionner cette page spécifique serait maintenant:

xPath = «/SmsFormData/Form/Pages/page [@ Id = "certains Guid"] »

Pour la sélection, je suis en utilisant le code vbscript suivant:

Set objDOM = CreateObject("Msxml2.DOMDocument.4.0") 

objDOM.async = false   
objDOM.load(file)  

set objNode = objDOM.selectSingleNode(xPath) 

le problème est maintenant que l'objet objNode est vide . Le noeud n'est pas sélectionné, mais pourquoi?

Oh, et par la manière: Merci pour le conseil Visual XPath!J'ai essayé de l'utiliser, mais malheureusement, il fait le chemin de l'énumération:/

+0

Vous devriez vraiment éditer votre question pour inclure ces détails – AnthonyWJones

0

Vous devez définir la langue de sélection à XPath en utilisant

objDOM.SetProperty « SelectionLanguage », « XPath »

Une fois que vous avez défini cette propriété, vous pouvez alors utiliser XPath complet pour accéder à tous les éléments que vous voulez

0

Si vous avez le navigateur Firefox, vous pouvez simplement installer l'inspecteur DOM (requis uniquement pour Firefox 3.0), et les extensions XPather. Ensuite, vous pouvez traverser vers le nœud que vous voulez dans la fenêtre Inspecteur DOM, et le XPath correspondant s'affichera dans la barre d'outils XPather dans la même fenêtre.

DOM Inspector: https://addons.mozilla.org/en-US/firefox/addon/6622

XPather: https://addons.mozilla.org/en-US/firefox/addon/1192?id=1192

Le XPather semble utiliser des attributs (et non énumération) chaque fois que possible d'identifier les noeuds (atleast qui est ce que je trouve dans ma petite expérimentation ...). Espérons que cela aide ...

0

Hm, ... J'ai l'impression que le problème doit être basé sur des fichiers. Même si je définis la propriété pour le langage SelectionLanguage et si j'utilise un XPath énuméré (que j'ai obtenu en utilisant le XPather de FireFox) le nœud Object reste toujours vide.

Est-ce que quelqu'un a une idée de ce qui pourrait se passer? Le fichier xml est fourni avec une application Microsoft et doit donc être valide. Au moins, je n'ai aucun problème lors de l'ouverture du fichier ou de son utilisation dans l'application, donc la syntaxe devrait être correcte.

Ou peut-être quelqu'un a-t-il une fonction vbscript qui parcourt tout le fichier xml pour trouver le nœud nécessaire afin de le supprimer?

+0

S'il vous plaît arrêter d'ajouter des réponses comme s'il s'agissait d'un forum de discussion, stackoverflow a un paradigme différent. – AnthonyWJones

0

Votre problème est que vous avez un espace de noms par défaut. L'espace de nom XPaths par défaut est toujours l'espace de noms 'no name'.

Vous devez: -

sNamespaces = "xmlns:cf='http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework'" 
objDOM.setProperty "SelectionNamespaces", sNamespaces 

vous pouvez utiliser dans votre XPath: -

xPath = "/cf:SmsFormData/cf:Form/cf:Pages/cf:Page[@Id=""some Guid""]" 
+0

Merci également, mais les crochets doivent être supprimés. -> objDOM.setPropery "SelectionNamespaces", sNamespaces – Marcus

0

Je ne sais pas si cela vous est utile, mais j'ai eu un problème similaire.

J'avais un fichier XML généré par l'application que je devais gérer. Il était du format: <LoginData> <GeneralData> <LoginMask>65537</LoginMask> </GeneralData> <UserData> <User> <Username>TEST0</Username> ... </User> <User> <Username>TEST1</Username> ... </User> </UserData> </LoginData>

Je devais faire correspondre sur un nom d'utilisateur et supprimer les autres étiquettes d'utilisateur.

Ça m'a pris (être un noob XML complet) âges pour travailler dehors, mais à la fin je frappe sur la correspondance sur un nœud, et la suppression de l'enfant du nœud parent:

pour chaque x oXmlDoc. documentElement.selectSingleNode ("UserData"). childNodes si x.getElementsByTagName ("Nom d'utilisateur"). item (0) .text = "TEST1" puis set exx = x.getElementsByTagName ("Nom d'utilisateur"). item (0) wscript.echo (x.getElementsByTagName ("nom d'utilisateur") élément (0) de .text.) WScript.Echo (x.nodename & ":" & x.text) x.parentNode.removeChild (x) end si suivant

Questions connexes