J'ai un fichier composé de documents XML valides concaténés. Je souhaite séparer efficacement des documents XML individuels.
Le contenu du fichier concaténé ressemblera à ceci, le fichier concaténé n'est donc pas un document XML valide. P>
<?xml version="1.0" encoding="UTF-8"?> <someData>...</someData> <?xml version="1.0" encoding="UTF-8"?> <someData>...</someData> <?xml version="1.0" encoding="UTF-8"?> <someData>...</someData>
5 Réponses :
Étant donné que vous n'êtes pas sûr que la déclaration sera toujours présente, vous pouvez supprimer toutes les déclarations (une regex tel que Dans un scénario similaire que j'ai rencontré, je lisai simplement le document concaténé directement à l'aide d'un analyseur XML: bien que le fichier concaténé peut ne pas être un document XML valide em>, il s'agit d'un XML Fragment EM> (sauf les déclarations répétées) - Donc, une fois que vous dépassez les déclarations, si votre analyseur prend en charge des fragments d'analyse, vous pouvez également simplement lire le résultat directement. Tous les éléments de niveau supérieur seront alors les éléments racines des documents concaténés. P>
En bref, si vous supprimez toutes les déclarations, vous aurez un fragment XML valide qui est trivialement paresible directement ou en l'entourant avec une balise. P> <\? xml version. * \?> code> peut les trouver), prépendez < Code>
DOC-COLLECTION> CODE>, telle que la chaîne résultante sera un document XML valide. Dans ce cas, vous pouvez récupérer les documents séparés en utilisant (par exemple) la requête XPath
/ doc-collection / * code>. Si le fichier combiné peut être suffisamment grand que la consommation de mémoire devient un problème, vous devrez peut-être utiliser un analyseur de streaming tel que sax, mais le principe reste le même. P>
Ne pas diviser! Ajoutez une grosse balise autour de là! Ensuite, il devient un fichier XML à nouveau:
<BIGTAG> <?xml version="1.0" encoding="UTF-8"?> <someData>...</someData> <?xml version="1.0" encoding="UTF-8"?> <someData>...</someData> <?xml version="1.0" encoding="UTF-8"?> <someData>...</someData> </BIGTAG>
Les instructions de traitement commençant par "XML" ou "XML" sont réservées aux normes XML, donc les utiliser comme "personnalisé", comme celui-ci n'est pas vraiment valide.
Je pense que cela est en grande partie correct que les instructions de traitement
Cela ne fonctionnera pas si tous les documents XML n'utilisent pas le même codage.
Vous devrez dépenser ces XML? choses>. Pourrait être possible dans le "Dump XML" -Stage.
C'est pourquoi j'ai suggéré de scinder à la place - c'est plus simple, éventuellement plus rapide et pas difficile à bien avoir raison.
@Amon, la scission est plus difficile si ces instructions de traitement ne sont pas toujours incluses. En outre, ces instructions n'ont pas de sens puisqu'elles n'utiliseront tous le même codage que le grand document. Java est assez bon à des expressions régulières, donc avec une expression simple que vous pourriez supprimer toutes ces instructions et que le reste deviendrait pure XML si vous le contenez dans une supertag.
@ Juha S., le codage est déjà invalide car tout est situé dans un seul fichier texte, il utilise ainsi le même codage.
Comme Eamon dit, si vous connaissez la chose XML> sera toujours là, rompre simplement sur cela. P>
omettre cela, recherchez l'étiquette de niveau de fin du document. Autrement dit, numérisez le texte comptant le nombre de niveaux que vous êtes profond. Chaque fois que vous voyez une balise qui commence par "<" mais pas "" et cela ne se termine pas avec "/>", ajoutez 1 au nombre de profondeurs. Chaque fois que vous voyez une balise qui commence "", soustraire 1. Chaque fois que vous soustrayez 1, vérifiez si vous êtes maintenant à zéro. Si tel est le cas, vous avez atteint la fin d'un document XML. P>
Pourquoi pas seulement chercher somédata>?
Et encore une fois, pourquoi ne pas supprimer les instructions de traitement, en ajoutant tout le reste dans une étiquette plus grande? L'instruction de traitement n'est plus utile que tous les fichiers utilisent le même codage que le grand document. Avec eux parti, y compris une super-balise vient de le transformer en XML valide à nouveau.
Cela dépend de la nécessité ultime. La question a été indiquée comme, comment puis-je les diviser ?, Voilà ce que j'essayais de répondre. Sans savoir ce que l'affiche originale essaie de faire avec la sortie, je ne sais pas si vous les enveloppez tous dans une grande balise est une solution viable ou non. Si c'est bien, allez-y. Il pourrait y avoir d'autres solutions potentielles dans cette direction. Comme si les fichiers partagent tous une étiquette commune de niveau supérieur, vous pouvez peut-être les combiner tous sous une seule tag de ce type, c'est-à-dire jeter les balises de démarrage sur toutes les étiquettes sauf et finales de tous sauf le dernier.
J'ai fini par casser les éléments racines de départ.
Je n'ai pas de réponse Java, mais voici comment j'ai résolu ce problème avec c #.
J'ai créé une classe nommée XMLFileStreams pour analyser le document source de la déclaration de document XML et la casser logiquement dans plusieurs documents: p> à utiliser xmlfiletreams: p> Il y a quelques mises en garde. P>
Ceci est ma réponse à la version C #. Code très laid qui fonctionne: - \
public List<T> ParseMultipleDocumentsByType<T>(string documents) { var cleanParsedDocuments = new List<T>(); var serializer = new XmlSerializer(typeof(T)); var flag = true; while (flag) { if(documents.Contains(typeof(T).Name)) { var startingPoint = documents.IndexOf("<?xml"); var endingString = "</" +typeof(T).Name + ">"; var endingPoing = documents.IndexOf(endingString) + endingString.Length; var document = documents.Substring(startingPoint, endingPoing - startingPoint); var singleDoc = (T)XmlDeserializeFromString(document, typeof(T)); cleanParsedDocuments.Add(singleDoc); documents = documents.Remove(startingPoint, endingPoing - startingPoint); } else { flag = false; } } return cleanParsedDocuments; } public static object XmlDeserializeFromString(string objectData, Type type) { var serializer = new XmlSerializer(type); object result; using (TextReader reader = new StringReader(objectData)) { result = serializer.Deserialize(reader); } return result; }
Supposons-nous que le codage du personnage reste le même pour chacun? Sinon, cela devient considérablement plus difficile :-)
Tous les fichiers utilisent le même codage que le document lui-même utilise. Peu importe s'ils disent qu'ils sont UTF-8. Si le document concatisé est formaté comme UTF-16, ils sont tous UTF-16.