web-dev-qa-db-ja.com

Java domを使用して、xmlから名前空間を削除するにはどうすればよいですか?

次のコードがあります

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();

その後、私は行うことができます

doc_.getDocumentElement();

最初の要素を取得しますが、問題はjobではなく、要素がtns:job

私は知っており、使用しようとしました:

dbFactory_.setNamespaceAware(true);

しかし、それは私が探しているものではありません。名前空間を完全に取り除くために何かが必要です。

どんな助けでも感謝します、ありがとう、

ジョシュ

13
Grammin

要素ノードと属性ノードの場合:

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

ノード名のローカル部分を提供します。

参照 Node.getLocalName()

5
robert_x44

Regex関数を使用します。これはこの問題を解決します:

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

can必要な場合は、XMLを前処理してすべての名前空間を削除します。 XMLドキュメントから名前空間を削除することは、本質的には、プログラミングフレームワークまたはライブラリから名前空間を削除することに相当するため、お勧めしません。名前が衝突する危険性があり、かつては区別されていなかった要素を区別できなくなります。しかし、それはあなたの葬式です。 ;-)

このXSLT変換は、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>

それをXMLドキュメントに適用します。 Javaこのようなことを行うための例は、このサイトでも十分にあるはずです。結果のドキュメントは、名前空間がなくてもまったく同じ構造とレイアウトになります。

3
Tomalak

のではなく

dbFactory_.setNamespaceAware(true);

使用する

dbFactory_.setNamespaceAware(false);

私はTomalakに同意しますが、一般に、名前空間は有害というよりも役立ちます。それらを使用したくないのですか?


編集:この答えは、名前空間prefixesを取り除く方法であるOPの質問には答えません。 RD01はそれに対する正しい答えを提供しました。

3
Anon
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

ソリューションを選択するときは、入力xmlのサイズも考慮する必要があります。サイズが〜100kの大きなxmlの場合、入力がWebサービスからのものである場合は可能ですが、大きな文字列を操作するときはガベージコレクションの影響も考慮する必要があります。以前はString.replaceAllを使用していましたが、replaceAllの実装方法が原因で、1.5GヒープサイズのOOMが頻繁に生成されました。

調査結果については http://app-inf.blogspot.com/2013/04/pitfalls-of-handling-large-string.html を参照できます。

XSLTが大きな文字列オブジェクトをどのように処理するかはわかりませんが、追加の大きなJavaオブジェクトの作成を回避するために、1つの解析でプレフィックスを削除するために手動で文字列を解析しました。

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、XSLTの1つの修正(3番目のテンプレート):

<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

TransformerFactoryを使用してから変換を呼び出す(空の名前空間を注入していた)代わりに、次のように変換しました。

    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();
1

名前空間の問題にも直面し、JavaでXMLファイルを読み取ることができませんでした。以下は解決策です:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);// this is imp code that will deactivate namespace in xml
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("XML/"+ fileName);
0
Arpana k