web-dev-qa-db-fra.com

Comment puis-je supprimer des espaces de noms du XML, en utilisant Java Dom?

J'ai le code suivant

DocumentBuilderFactory dbFactory_ = DocumentBuilderFactory.newInstance();
Document doc_;
DocumentBuilder dBuilder = dbFactory_.newDocumentBuilder();
StringReader reader = new StringReader(s);
InputSource inputSource = new InputSource(reader);
doc_ = dBuilder.parse(inputSource);
doc_.getDocumentElement().normalize();

Alors je peux faire

doc_.getDocumentElement();

et obtenir mon premier élément, mais le problème est qu'au lieu d'être job, l'élément est tns:job.

Je connais et ai essayé d'utiliser:

dbFactory_.setNamespaceAware(true);

mais ce n'est tout simplement pas ce que je recherche, j'ai besoin de quelque chose pour me débarrasser complètement des espaces de noms.

Toute aide serait appréciée Merci,

Josh

12
Grammin

Pour les nœuds d'élément et d'attribut:

Node node = ...;
String name = node.getLocalName();

vous donnera la partie locale du nom du nœud.

Voir Node.getLocalName ()

4
robert_x44

Utilisez la fonction Regex. Cela résoudra ce problème:

public static String removeXmlStringNamespaceAndPreamble(String xmlString) {
  return xmlString.replaceAll("(<\\?[^<]*\\?>)?", ""). /* remove preamble */
  replaceAll("xmlns.*?(\"|\').*?(\"|\')", "") /* remove xmlns declaration */
  .replaceAll("(<)(\\w+:)(.*?>)", "$1$3") /* remove opening tag prefix */
  .replaceAll("(</)(\\w+:)(.*?>)", "$1$3"); /* remove closing tags prefix */
}
11
Habeeb

Plutôt que 

dbFactory_.setNamespaceAware(true);

Utilisation

dbFactory_.setNamespaceAware(false);

Bien que je sois d’accord avec Tomalak: en général, les espaces de noms sont plus utiles que nuisibles. Pourquoi ne veux-tu pas les utiliser?


Edit: cette réponse ne répond pas à la question du PO, qui était comment se débarrasser de l'espace de nom préfixes . RD01 a fourni la bonne réponse à cette question.

3
Anon

Vous pouvez pré-traiter XML pour supprimer tous les espaces de noms, si vous devez absolument le faire. Je vous le déconseille, car la suppression d'espaces de nom d'un document XML est essentiellement comparable à la suppression d'espaces de nom d'un cadre de programmation ou d'une bibliothèque: vous risqueriez des conflits de noms et vous perdriez la possibilité de différencier des éléments uniques. Cependant, ce sont vos funérailles. ;-)

Cette transformation XSLT supprime tous les espaces de nom de tout document XML.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:apply-templates select="node()|@*" />
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

Appliquez-le à votre document XML. Les exemples de Java pour faire une telle chose devraient être nombreux, même sur ce site. Le document résultant sera exactement de la même structure et de la même présentation, sans espaces de noms.

2
Tomalak
public static void wipeRootNamespaces(Document xml) {       
    Node root = xml.getDocumentElement();
    NodeList rootchildren = root.getChildNodes();
    Element newroot = xml.createElement(root.getNodeName());

    for (int i=0;i<rootchildren.getLength();i++) {
        newroot.appendChild(rootchildren.item(i).cloneNode(true));
    }

    xml.replaceChild(newroot, root);
}
2
Kermit

La taille du fichier XML d'entrée doit également être prise en compte lors du choix de la solution. Pour les fichiers xml volumineux, d'une taille d'environ 100 Ko, si votre entrée provient d'un service Web, vous devez également prendre en compte les implications de la récupération de place lorsque vous manipulez une chaîne volumineuse. Nous avions déjà utilisé String.replaceAll auparavant, ce qui entraînait de fréquentes MOO en production avec une taille de segment de mémoire de 1,5 G en raison de la façon dont replaceAll était implémenté. 

Vous pouvez consulter http://app-inf.blogspot.com/2013/04/pitfalls-of-handling-large-string.html pour nos résultats.

Je ne suis pas sûr de savoir comment XSLT traite les grands objets String, mais nous avons fini par analyser la chaîne manuellement pour supprimer les préfixes en une analyse afin d'éviter de créer d'autres objets Java volumineux.

public static String removePrefixes(String input1) {
    String ret = null;
    int strStart = 0;
    boolean finished = false;
    if (input1 != null) {
        //BE CAREFUL : allocate enough size for StringBuffer to avoid expansion
        StringBuffer sb = new StringBuffer(input1.length()); 
        while (!finished) {

            int start = input1.indexOf('<', strStart);
            int end = input1.indexOf('>', strStart);
            if (start != -1 && end != -1) {
                // Appending anything before '<', including '<'
                sb.append(input1, strStart, start + 1);

                String tag = input1.substring(start + 1, end);
                if (tag.charAt(0) == '/') {
                    // Appending '/' if it is "</"
                    sb.append('/');
                    tag = tag.substring(1);
                }

                int colon = tag.indexOf(':');
                int space = tag.indexOf(' ');
                if (colon != -1 && (space == -1 || colon < space)) {
                    tag = tag.substring(colon + 1);
                }
                // Appending tag with prefix removed, and ">"
                sb.append(tag).append('>');
                strStart = end + 1;
            } else {
                finished = true;
            }
        }
        //BE CAREFUL : use new String(sb) instead of sb.toString for large Strings
        ret = new String(sb);
    }
    return ret;
}
1
user1738754

Tomalak, un correctif de votre XSLT (dans le 3ème modèle):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="node()">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="node() | @*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="@*">
    <!-- Here! -->
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>

  </xsl:template>
</xsl:stylesheet>
1
dzav

Au lieu d'utiliser TransformerFactory et ensuite d'appeler transform sur celui-ci (qui injectait l'espace de nom vide, j'ai transformé comme suit:

    OutputStream outputStream = new FileOutputStream(new File(xMLFilePath));
    OutputFormat outputFormat = new OutputFormat(doc, "UTF-8", true);
    outputFormat.setOmitComments(true);
    outputFormat.setLineWidth(0);

    XMLSerializer serializer = new XMLSerializer(outputStream, outputFormat);
    serializer.serialize(doc);
    outputStream.close();
0
Sulaiman Karmali