কীভাবে জাভা থেকে এক্সএমএল প্রিন্ট করবেন?


443

আমার কাছে একটি জাভা স্ট্রিং রয়েছে যাতে এক্সএমএল রয়েছে, কোনও লাইন ফিড বা ইন্ডেন্টেশন ছাড়াই। আমি এটিকে সুন্দর বিন্যাসিত এক্সএমএল দিয়ে একটি স্ট্রিংয়ে পরিণত করতে চাই। আমি এটা কিভাবে করবো?

String unformattedXml = "<tag><nested>hello</nested></tag>";
String formattedXml = new [UnknownClass]().format(unformattedXml);

দ্রষ্টব্য: আমার ইনপুটটি একটি স্ট্রিং । আমার আউটপুট একটি স্ট্রিং

(বেসিক) মক ফলাফল:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <tag>
    <nested>hello</nested>
  </tag>
</root>

: এই প্রশ্ন পরীক্ষা stackoverflow.com/questions/1264849/...
DFA

10
কেবল কৌতূহলী, আপনি কি এই এক্সপুটটি কোনও এক্সএমএল ফাইল বা অন্য কোনও কিছুতে প্রেরণ করছেন যেখানে সত্যিকারের ইনডেন্টিং গুরুত্বপূর্ণ? কিছু সময় আগে আমি আমার এক্সএমএলটি সঠিকভাবে প্রদর্শিত করার জন্য ফর্ম্যাট করার বিষয়ে খুব উদ্বিগ্ন ছিলাম ... তবে এটির জন্য বেশ কিছুটা সময় ব্যয় করার পরে আমি বুঝতে পেরেছিলাম যে আমার আউটপুটটি একটি ওয়েব ব্রাউজারে এবং কোনও অপেক্ষাকৃত আধুনিক ওয়েব ব্রাউজারে পাঠাতে হবে had XML প্রকৃতপক্ষে একটি সুন্দর গাছের কাঠামোতে প্রদর্শিত হবে, তাই আমি এই সমস্যাটি ভুলে গিয়ে এগিয়ে যেতে পারি। আপনি (বা একই সমস্যাযুক্ত অন্যান্য ব্যবহারকারী) একই বিবরণ উপেক্ষা করতে পারতেন এমন ক্ষেত্রে আমি এটি উল্লেখ করছি।
আবেল

3
@ আবেল, পাঠ্য ফাইলগুলিতে সঞ্চয় করা, এইচটিএমএল টেক্সারিয়াস প্রবেশ করানো এবং ডিবাগিংয়ের উদ্দেশ্যে কনসোলে ডাম্প করা।
স্টিভ ম্যাকলিউড

2
"অত্যধিক বিস্তৃত হিসাবে ধরে রাখুন" - বর্তমানে যে প্রশ্নটি করা হচ্ছে তার থেকে বেশি সুনির্দিষ্ট হওয়া শক্ত!
স্টিভ ম্যাকলিড

উত্তর:


266
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
//initialize StreamResult with File object to save to file
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
String xmlString = result.getWriter().toString();
System.out.println(xmlString);

দ্রষ্টব্য: জাভা সংস্করণের উপর নির্ভর করে ফলাফলগুলি পৃথক হতে পারে। আপনার প্ল্যাটফর্মের সাথে সম্পর্কিত কাজের ক্ষেত্রগুলির জন্য অনুসন্ধান করুন।


1
কীভাবে এটি তৈরি করবেন যাতে আউটপুটটি অভ্যস্ত হয় না <?xml version="1.0" encoding="UTF-8"?>?
থ্যাং ফ্যাম

19
<?xml ...>ঘোষণা বাদ দিতে , জুড়ুনtransformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
রাস্টিক্স

4
নৈমিত্তিক পাঠকরা এখানে বর্ণিত সমাধানের উন্নত সংস্করণটি ( স্ট্যাকওভারফ্লো . com / a / 33541820 / 363573 ) ব্যবহার করতে পারেন।
স্টিফান

5
docসংজ্ঞায়িত কোথায় ?
ফ্লোরিয়ান এফ

6
এটি আমার প্রশ্নের উত্তর দেয় না: এক্সএমএলযুক্ত স্ট্রিংকে আমি কীভাবে ফর্ম্যাট করব? এই উত্তরটি ইতিমধ্যে ধরে নিয়েছে যে আপনি কোনওভাবে স্ট্রিং অবজেক্টটিকে অন্য কোনও বস্তুতে রূপান্তর করেছেন।
স্টিভ ম্যাকলিউড

135

আমার নিজের প্রশ্নের উত্তর এখানে। এক্সএমএল প্রিন্ট করে এমন একটি ক্লাস লিখতে আমি বিভিন্ন ফলাফলের উত্তরগুলি একত্রিত করেছিলাম।

এটি কীভাবে অবৈধ এক্সএমএল বা বড় দলিলগুলির সাথে প্রতিক্রিয়া জানায় তার কোনও গ্যারান্টি নেই।

package ecb.sdw.pretty;

import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

/**
 * Pretty-prints xml, supplied as a string.
 * <p/>
 * eg.
 * <code>
 * String formattedXml = new XmlFormatter().format("<tag><nested>hello</nested></tag>");
 * </code>
 */
public class XmlFormatter {

    public XmlFormatter() {
    }

    public String format(String unformattedXml) {
        try {
            final Document document = parseXmlFile(unformattedXml);

            OutputFormat format = new OutputFormat(document);
            format.setLineWidth(65);
            format.setIndenting(true);
            format.setIndent(2);
            Writer out = new StringWriter();
            XMLSerializer serializer = new XMLSerializer(out, format);
            serializer.serialize(document);

            return out.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private Document parseXmlFile(String in) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            InputSource is = new InputSource(new StringReader(in));
            return db.parse(is);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (SAXException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String unformattedXml =
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><QueryMessage\n" +
                        "        xmlns=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message\"\n" +
                        "        xmlns:query=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query\">\n" +
                        "    <Query>\n" +
                        "        <query:CategorySchemeWhere>\n" +
                        "   \t\t\t\t\t         <query:AgencyID>ECB\n\n\n\n</query:AgencyID>\n" +
                        "        </query:CategorySchemeWhere>\n" +
                        "    </Query>\n\n\n\n\n" +
                        "</QueryMessage>";

        System.out.println(new XmlFormatter().format(unformattedXml));
    }

}

13
কেবলমাত্র এই উত্তরটির জন্য জেরেস ব্যবহার করা প্রয়োজন। আপনি যদি এই নির্ভরতাটি যুক্ত করতে না চান তবে আপনি কেবলমাত্র স্ট্যান্ডার্ড জেডিকে গ্রন্থাগার এবং javax.xML.transfor.Transformer (নীচে আমার উত্তর দেখুন) ব্যবহার করতে পারেন
খাইলো

45
২০০৮ সালে এটি একটি ভাল উত্তর ছিল, তবে এখন এটি সমস্ত অ্যাপাচি ক্লাসের চেয়ে মানক জেডিকে ক্লাসে করা যেতে পারে। Xerces.apache.org/xerces2-j/faq-general.html#faq-6 দেখুন । হ্যাঁ এটি একটি জেরেসেস এফএকিউ তবে উত্তরটি মানক জেডিকে ক্লাসগুলিকে অন্তর্ভুক্ত করে। এই ক্লাসগুলির প্রাথমিক 1.5 টি প্রয়োগের অনেকগুলি সমস্যা ছিল তবে 1.6 থেকে সবকিছু সূক্ষ্মভাবে কাজ করে। এফএকিউতে এলএসএসেরাইজার উদাহরণটি অনুলিপি করুন, "..." বিটটি কেটে লাইনটির writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);পরে যুক্ত করুন LSSerializer writer = ...
জর্জ হকিন্স

2
আমি অ্যাপাচি যে উদাহরণটি দিয়েছি তা ব্যবহার করে একটি ছোট শ্রেণি তৈরি করেছি, যা @ জর্জহকিন্স একটি লিঙ্ক দিয়েছে। ভেরিয়েবলটি কীভাবে documentআরম্ভ করা হয়েছিল তা অনুপস্থিত ছিল, তাই আমি ভেবেছিলাম যে আমি হতাশায় যুক্ত হতে পারি এবং এর থেকে একটি দ্রুত উদাহরণ তৈরি করতে পারি। আমাকে কিছু পরিবর্তন করা উচিত কিনা তা আমাকে জানান, পেস্টবিন.
com

এটি কেবল jdk দিয়ে করতে পারেন তা সত্য নয়। অন্তত নির্ভরযোগ্যভাবে না। এটি কিছু অভ্যন্তরীণ রেজিস্ট্রি প্রয়োগের উপর নির্ভর করে যা আমার jdk7u72 এর সাথে ডিফল্টরূপে সক্রিয় নয়। সুতরাং আপনি এখনও সরাসরি অ্যাপাচি স্টাফ ব্যবহার করতে পারেন।
ব্যবহারকারী 1050755

এখানে কোনও নির্ভরতা ছাড়াই একটি সমাধান: stackoverflow.com/a/33541820/363573
স্টিফান

131

এই উত্তরের উপর ভিত্তি করে একটি সহজ সমাধান :

public static String prettyFormat(String input, int indent) {
    try {
        Source xmlInput = new StreamSource(new StringReader(input));
        StringWriter stringWriter = new StringWriter();
        StreamResult xmlOutput = new StreamResult(stringWriter);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        transformerFactory.setAttribute("indent-number", indent);
        Transformer transformer = transformerFactory.newTransformer(); 
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.transform(xmlInput, xmlOutput);
        return xmlOutput.getWriter().toString();
    } catch (Exception e) {
        throw new RuntimeException(e); // simple exception handling, please review it
    }
}

public static String prettyFormat(String input) {
    return prettyFormat(input, 2);
}

পরীক্ষা ক্ষেত্রে:

prettyFormat("<root><child>aaa</child><child/></root>");

আয়:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <child>aaa</child>
  <child/>
</root>

1
এই কোডটি আমি সর্বদা ব্যবহার করেছি তবে এই সংস্থায় এটি কাজ করে না, আমি ধরে নিয়েছি তারা অন্য একটি এক্সএমএল রূপান্তরকারী লাইব্রেরি ব্যবহার করছে। আমি কারখানাটি একটি পৃথক লাইন হিসাবে তৈরি করেছি এবং তারপর করেছি factory.setAttribute("indent-number", 4);এবং এখন এটি কাজ করে।
অ্যাড্রিয়ান স্মিথ

কীভাবে এটি তৈরি করবেন যাতে আউটপুটটি অভ্যস্ত হয় না <?xml version="1.0" encoding="UTF-8"?>?
থ্যাং ফাম

4
@ হ্যারি:transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
jjmontes

5
হাই আমি এই সঠিক কোডটি ব্যবহার করছি, এবং খনি উপাদানগুলি প্রথম উপাদানটিকে বাদ দিয়ে সঠিকভাবে তাই, এটি: <?xml version="1.0" encoding="UTF-8"?><root>সমস্ত এক লাইনে is কোন ধারণা কেন?
কোডিেকে

2
@Codemiester: একটি বাগ (দেখুন মনে করা হয় stackoverflow.com/a/18251901/3375325 )। অ্যাডিং transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");আমার জন্য কাজ করে।
jansohn

100

এখন এটি 2012 এবং জাভা এক্সএমএল এর সাথে আগের চেয়ে বেশি কিছু করতে পারে, আমি আমার গৃহীত উত্তরের একটি বিকল্প যুক্ত করতে চাই। জাভা 6 এর বাইরে এর কোনও নির্ভরতা নেই।

import org.w3c.dom.Node;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

/**
 * Pretty-prints xml, supplied as a string.
 * <p/>
 * eg.
 * <code>
 * String formattedXml = new XmlFormatter().format("<tag><nested>hello</nested></tag>");
 * </code>
 */
public class XmlFormatter {

    public String format(String xml) {

        try {
            final InputSource src = new InputSource(new StringReader(xml));
            final Node document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(src).getDocumentElement();
            final Boolean keepDeclaration = Boolean.valueOf(xml.startsWith("<?xml"));

        //May need this: System.setProperty(DOMImplementationRegistry.PROPERTY,"com.sun.org.apache.xerces.internal.dom.DOMImplementationSourceImpl");


            final DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
            final DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
            final LSSerializer writer = impl.createLSSerializer();

            writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE); // Set this to true if the output needs to be beautified.
            writer.getDomConfig().setParameter("xml-declaration", keepDeclaration); // Set this to true if the declaration is needed to be outputted.

            return writer.writeToString(document);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String unformattedXml =
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><QueryMessage\n" +
                        "        xmlns=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message\"\n" +
                        "        xmlns:query=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query\">\n" +
                        "    <Query>\n" +
                        "        <query:CategorySchemeWhere>\n" +
                        "   \t\t\t\t\t         <query:AgencyID>ECB\n\n\n\n</query:AgencyID>\n" +
                        "        </query:CategorySchemeWhere>\n" +
                        "    </Query>\n\n\n\n\n" +
                        "</QueryMessage>";

        System.out.println(new XmlFormatter().format(unformattedXml));
    }
}

কোনও ইন্ডেনশন নয়, তবে এটি এর সাথে কাজ করে: System.setProperty (DOMImplementationRegistry.PROPERTY, "com.sun.org.apache.xerces.intern.dom.DOMImplementationSourceImpl");
ggb667

1
এই উদাহরণটিতে আপনি কীভাবে ইন্ডেনশন যুক্ত করবেন?
ggb667

2
@ ড্যানটেম্পল মনে হচ্ছে এনকোডিংটি নিয়ন্ত্রণ করতে আপনার এলএসআউটপুট ব্যবহার করা উচিত। চিপকিলমার.নেট
জোশুয়া ডেভিস

1
আমি এটিকে Andriod এ ব্যবহার করার চেষ্টা করেছি কিন্তু আমি প্যাকেজটি OM DOMImplementationRegistry সন্ধান করতে সক্ষম নই। আমি জাভা 8 ব্যবহার করছি
চিন্তন সনি

2
আমদানি তালিকাটি অন্তর্ভুক্ত করার জন্য ধন্যবাদ, অন্যথায় প্রয়োজনীয় সংমিশ্রণটি অনুধাবন করার জন্য প্রচুর বিবাদী প্যাকেজগুলি উপলভ্য ..
লিওন

54

কেবলমাত্র শীর্ষ রেট করা উত্তরের জন্য জেরেস ব্যবহার করা প্রয়োজন note

আপনি যদি এই বাহ্যিক নির্ভরতা যুক্ত করতে না চান তবে আপনি কেবল স্ট্যান্ডার্ড জেডিকে গ্রন্থাগারগুলি (যা প্রকৃতপক্ষে অভ্যন্তরীণভাবে জেরেস ব্যবহার করে নির্মিত) ব্যবহার করতে পারেন।

এনবি jdk সংস্করণ 1.5 দেখুন সঙ্গে একটি বাগ ছিল http://bugs.sun.com/bugdatedia/view_bug.do?bug_id=6296446 তবে এটি এখনই সমাধান হয়েছে,

(দ্রষ্টব্য যদি কোনও ত্রুটি দেখা দেয় তবে এটি আসল পাঠ্যটি ফিরিয়ে দেবে)

package com.test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.InputSource;

public class XmlTest {
    public static void main(String[] args) {
        XmlTest t = new XmlTest();
        System.out.println(t.formatXml("<a><b><c/><d>text D</d><e value='0'/></b></a>"));
    }

    public String formatXml(String xml){
        try{
            Transformer serializer= SAXTransformerFactory.newInstance().newTransformer();
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            //serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            //serializer.setOutputProperty("{http://xml.customer.org/xslt}indent-amount", "2");
            Source xmlSource=new SAXSource(new InputSource(new ByteArrayInputStream(xml.getBytes())));
            StreamResult res =  new StreamResult(new ByteArrayOutputStream());            
            serializer.transform(xmlSource, res);
            return new String(((ByteArrayOutputStream)res.getOutputStream()).toByteArray());
        }catch(Exception e){
            //TODO log error
            return xml;
        }
    }

}

এই ক্ষেত্রে বাম ট্যাব ব্যবহার করা হয় না। সমস্ত ট্যাগ স্বাভাবিক পাঠ্যের মতো লাইনটির প্রথম প্রতীক থেকে শুরু হয়।
Ruslan

বাইটস এবং স্ট্রিংয়ের মধ্যে পিছনে পিছনে রূপান্তর করার সময় আপনার একটি চরসেট নির্দিষ্ট করার দরকার নেই?
উইল গ্লাস

2
আরে / স্ট্রিং থেকে বাইট এবং রূপান্তর করার দরকার নেই। এটি করার সময় খুব কমপক্ষে আপনাকে চরসেট নির্দিষ্ট করতে হবে। স্ট্রিংরেডার এবং স্ট্রিং রাইটার ক্লাসগুলি ইনপুটসোর্স এবং স্ট্রিমরসাল্টে মোড়ানো ব্যবহার করা ভাল বিকল্প।
ম্যাক্সিমডিম

কাজ করছে না. কিছু অভ্যন্তরীণ রেজিস্ট্রি প্রয়োগের সাথে আপনার চারপাশে জগাখিচু করা দরকার।
ব্যবহারকারী 1050755

এখানে এই সমাধানের একটি সহজ বৈকল্পিক: stackoverflow.com/a/33541820/363573
স্টিফান

32

আমি অতীতে org.dom4j.io.OutputFormat.createPrettyPress () পদ্ধতি ব্যবহার করে প্রিন্ট করেছি

public String prettyPrint(final String xml){  

    if (StringUtils.isBlank(xml)) {
        throw new RuntimeException("xml was null or blank in prettyPrint()");
    }

    final StringWriter sw;

    try {
        final OutputFormat format = OutputFormat.createPrettyPrint();
        final org.dom4j.Document document = DocumentHelper.parseText(xml);
        sw = new StringWriter();
        final XMLWriter writer = new XMLWriter(sw, format);
        writer.write(document);
    }
    catch (Exception e) {
        throw new RuntimeException("Error pretty printing xml:\n" + xml, e);
    }
    return sw.toString();
}

3
স্বীকৃত সমাধানটি আমার ক্ষেত্রে নেস্টেড ট্যাগগুলি সঠিকভাবে ইনডেন্ট করে না, এটি এটি করে।
চেজ সেয়বার্ট

3
আমি লাইনের শেষে সমস্ত prettyPrintedString.replaceAll("\\s+\n", "\n")
অনুসরণযোগ্য

19

Dom4j ব্যবহার করে এটি করার একটি উপায় এখানে রয়েছে :

আমদানি:

import org.dom4j.Document;  
import org.dom4j.DocumentHelper;  
import org.dom4j.io.OutputFormat;  
import org.dom4j.io.XMLWriter;

কোড:

String xml = "<your xml='here'/>";  
Document doc = DocumentHelper.parseText(xml);  
StringWriter sw = new StringWriter();  
OutputFormat format = OutputFormat.createPrettyPrint();  
XMLWriter xw = new XMLWriter(sw, format);  
xw.write(doc);  
String result = sw.toString();

1
এটি আমার পক্ষে কাজ করে নি। এটি ঠিক এর মতো কিছু দিয়েছে: <?xml version...এক লাইনে এবং অন্য লাইনে সমস্ত কিছু।
ষাট ফুটারসুডে

14

যেহেতু আপনি একটি দিয়ে শুরু করছেন String, আপনি এটি ব্যবহার করার আগে আপনাকে কোনও DOMঅবজেক্টে (উদাহরণস্বরূপ Node) গুপ্ত হওয়া দরকার Transformer। তবে, যদি আপনি জানেন যে আপনার এক্সএমএল স্ট্রিংটি বৈধ, এবং আপনি কোনও স্ট্রিংকে ডিওমে বিভক্ত করার জন্য মেমরির ওভারহেডটি চাপাতে চান না, তারপরে স্ট্রিং ফিরে পেতে ডমের উপর একটি রূপান্তর চলমান - আপনি কেবল কিছু পুরানো ফ্যাশন করতে পারেন চরিত্র বিশ্লেষণ দ্বারা অক্ষর। প্রতিটি </...>অক্ষরের পরে একটি নতুন লাইন এবং স্পেস সন্নিবেশ করান, প্রতিটির জন্য বাড়ানো কাউন্ট (স্পেসের সংখ্যা নির্ধারণের জন্য) রাখুন এবং ইনডেন্ট করুন <...>এবং </...>আপনি প্রত্যেকে দেখতে পাচ্ছেন এমন হ্রাস পাবে।

দাবি অস্বীকার - আমি নীচের ফাংশনগুলির একটি কাটা / পেস্ট / পাঠ্য সম্পাদনা করেছি, সুতরাং তারা যেমনটি সংকলন করতে পারে না।

public static final Element createDOM(String strXML) 
    throws ParserConfigurationException, SAXException, IOException {

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setValidating(true);
    DocumentBuilder db = dbf.newDocumentBuilder();
    InputSource sourceXML = new InputSource(new StringReader(strXML));
    Document xmlDoc = db.parse(sourceXML);
    Element e = xmlDoc.getDocumentElement();
    e.normalize();
    return e;
}

public static final void prettyPrint(Node xml, OutputStream out)
    throws TransformerConfigurationException, TransformerFactoryConfigurationError, TransformerException {
    Transformer tf = TransformerFactory.newInstance().newTransformer();
    tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    tf.setOutputProperty(OutputKeys.INDENT, "yes");
    tf.transform(new DOMSource(xml), new StreamResult(out));
}

1
"তবে, আপনি যদি জানেন তবে আপনার এক্সএমএল স্ট্রিংটি বৈধ ..." ভাল পয়েন্ট। নীচের এই পদ্ধতির উপর ভিত্তি করে আমার সমাধান দেখুন।
ডেভিড ইজলি

12

যদি কোনও তৃতীয় পক্ষের এক্সএমএল লাইব্রেরি ব্যবহার করা ঠিক থাকে তবে আপনি বর্তমানে সর্বাধিক-ভোট প্রাপ্ত উত্তরগুলি যা বলে তার চেয়ে উল্লেখযোগ্য সরল কিছু দিয়ে আপনি পালাতে পারেন ।

এটি উল্লিখিত ছিল যে ইনপুট এবং আউটপুট উভয়ই স্ট্রিংস হওয়া উচিত, সুতরাং এখানে একটি ইউটিলিটি পদ্ধতি যা এক্সওএম লাইব্রেরি দ্বারা প্রয়োগ করা হয়েছে কেবল এটিই করে :

import nu.xom.*;
import java.io.*;

[...]

public static String format(String xml) throws ParsingException, IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Serializer serializer = new Serializer(out);
    serializer.setIndent(4);  // or whatever you like
    serializer.write(new Builder().build(xml, ""));
    return out.toString("UTF-8");
}

আমি পরীক্ষা করেছি যে এটি কাজ করে এবং ফলাফলগুলি আপনার জেআরই সংস্করণ বা এর মতো কোনও কিছুর উপর নির্ভর করে না । কীভাবে আপনার পছন্দ অনুসারে আউটপুট ফর্ম্যাটটি কাস্টমাইজ করতে হয় তা দেখতে, Serializerএপিআই দেখুন।

এটি আসলে আমার ভাবনার চেয়ে বেশি সময় ধরে বেরিয়ে এসেছিল - কিছু অতিরিক্ত লাইন প্রয়োজন ছিল কারণ এটি লিখতে Serializerচায় OutputStream। তবে মনে রাখবেন যে এখানে প্রকৃত এক্সএমএল টুইডলিংয়ের জন্য খুব কম কোড রয়েছে।

(এই উত্তরটি এক্সওএমের আমার মূল্যায়নের অংশ, যা ডম 4 জে প্রতিস্থাপনের জন্য সেরা জাভা এক্সএমএল লাইব্রেরি সম্পর্কে আমার প্রশ্নের একটি বিকল্প হিসাবে পরামর্শ দেওয়া হয়েছিল । রেকর্ডের জন্য, ডম 4 জে সহ আপনি একইভাবে সহজেই ব্যবহার করে এটি অর্জন করতে পারেন এবংXMLWriterOutputFormatসম্পাদনা : .. .এমনেক 55 এর উত্তরে প্রদর্শিত হয়েছে ))


2
ধন্যবাদ, আমি যা খুঁজছিলাম যদি আপনার একটি এক্সএমএল ইতিমধ্যে কোনও "ডকুমেন্ট" অবজেক্টে এক্সওএম দিয়ে বিশ্লেষণ করে থাকে তবে আপনি এটিকে সরাসরি সিরিয়ালাইজার.ওরাইট (নথি) এ পাস করতে পারেন;
থিবল্ট ডি

12

কেভিন হাকানসন বলেছিলেন: "তবে, আপনি যদি নিজের এক্সএমএল স্ট্রিংটি বৈধ বলে জানেন এবং আপনি কোনও স্ট্রিংকে ডিওমে বিভক্ত করার জন্য মেমরির ওভারহেডটি দিতে না চান, তবে স্ট্রিং ফিরে পাওয়ার জন্য ডমের উপর একটি রূপান্তর চালিয়ে যেতে পারেন - আপনি কেবল অক্ষর বিশ্লেষণ করে কিছু পুরানো ফ্যাশন চরিত্রটি করুন every প্রতিটি অক্ষরের পরে একটি নতুন লাইন এবং স্পেসগুলি সন্নিবেশ করুন, রাখুন এবং ইনডেন্টের কাউন্টার রাখুন (স্পেসের সংখ্যা নির্ধারণ করতে) যা আপনি প্রতি <...> এর জন্য বৃদ্ধি করেন এবং আপনার দেখা প্রত্যেকটির জন্য হ্রাস ""

একমত। এই জাতীয় দৃষ্টিভঙ্গি অনেক দ্রুত এবং এর চেয়ে কম নির্ভরতা রয়েছে।

উদাহরণ সমাধান:

/**
 * XML utils, including formatting.
 */
public class XmlUtils
{
  private static XmlFormatter formatter = new XmlFormatter(2, 80);

  public static String formatXml(String s)
  {
    return formatter.format(s, 0);
  }

  public static String formatXml(String s, int initialIndent)
  {
    return formatter.format(s, initialIndent);
  }

  private static class XmlFormatter
  {
    private int indentNumChars;
    private int lineLength;
    private boolean singleLine;

    public XmlFormatter(int indentNumChars, int lineLength)
    {
      this.indentNumChars = indentNumChars;
      this.lineLength = lineLength;
    }

    public synchronized String format(String s, int initialIndent)
    {
      int indent = initialIndent;
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < s.length(); i++)
      {
        char currentChar = s.charAt(i);
        if (currentChar == '<')
        {
          char nextChar = s.charAt(i + 1);
          if (nextChar == '/')
            indent -= indentNumChars;
          if (!singleLine)   // Don't indent before closing element if we're creating opening and closing elements on a single line.
            sb.append(buildWhitespace(indent));
          if (nextChar != '?' && nextChar != '!' && nextChar != '/')
            indent += indentNumChars;
          singleLine = false;  // Reset flag.
        }
        sb.append(currentChar);
        if (currentChar == '>')
        {
          if (s.charAt(i - 1) == '/')
          {
            indent -= indentNumChars;
            sb.append("\n");
          }
          else
          {
            int nextStartElementPos = s.indexOf('<', i);
            if (nextStartElementPos > i + 1)
            {
              String textBetweenElements = s.substring(i + 1, nextStartElementPos);

              // If the space between elements is solely newlines, let them through to preserve additional newlines in source document.
              if (textBetweenElements.replaceAll("\n", "").length() == 0)
              {
                sb.append(textBetweenElements + "\n");
              }
              // Put tags and text on a single line if the text is short.
              else if (textBetweenElements.length() <= lineLength * 0.5)
              {
                sb.append(textBetweenElements);
                singleLine = true;
              }
              // For larger amounts of text, wrap lines to a maximum line length.
              else
              {
                sb.append("\n" + lineWrap(textBetweenElements, lineLength, indent, null) + "\n");
              }
              i = nextStartElementPos - 1;
            }
            else
            {
              sb.append("\n");
            }
          }
        }
      }
      return sb.toString();
    }
  }

  private static String buildWhitespace(int numChars)
  {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < numChars; i++)
      sb.append(" ");
    return sb.toString();
  }

  /**
   * Wraps the supplied text to the specified line length.
   * @lineLength the maximum length of each line in the returned string (not including indent if specified).
   * @indent optional number of whitespace characters to prepend to each line before the text.
   * @linePrefix optional string to append to the indent (before the text).
   * @returns the supplied text wrapped so that no line exceeds the specified line length + indent, optionally with
   * indent and prefix applied to each line.
   */
  private static String lineWrap(String s, int lineLength, Integer indent, String linePrefix)
  {
    if (s == null)
      return null;

    StringBuilder sb = new StringBuilder();
    int lineStartPos = 0;
    int lineEndPos;
    boolean firstLine = true;
    while(lineStartPos < s.length())
    {
      if (!firstLine)
        sb.append("\n");
      else
        firstLine = false;

      if (lineStartPos + lineLength > s.length())
        lineEndPos = s.length() - 1;
      else
      {
        lineEndPos = lineStartPos + lineLength - 1;
        while (lineEndPos > lineStartPos && (s.charAt(lineEndPos) != ' ' && s.charAt(lineEndPos) != '\t'))
          lineEndPos--;
      }
      sb.append(buildWhitespace(indent));
      if (linePrefix != null)
        sb.append(linePrefix);

      sb.append(s.substring(lineStartPos, lineEndPos + 1));
      lineStartPos = lineEndPos + 1;
    }
    return sb.toString();
  }

  // other utils removed for brevity
}

2
এভাবেই করা উচিত। স্ট্রিং স্তরে ফ্লাইতে ফর্ম্যাট করুন। এটিই একমাত্র সমাধান যা অবৈধ বা অসম্পূর্ণ এক্সএমএল ফর্ম্যাট করবে।
ফ্লোরিয়ান এফ

11

হুমমম ... এরকম কিছুর মুখোমুখি হয়েছিল এবং এটি একটি জানা বাগ ... কেবলমাত্র এই আউটপুটপ্রপারটি যুক্ত করুন ..

transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "8");

আশাকরি এটা সাহায্য করবে ...


2
এই আউটপুটপ্রাপ্তির কারখানাটি কোথা থেকে আসে?
হেলেনভ

আমদানি com.sun.org.apache.xML.intern.serializer। *;
গৌরব

9

"আপনার অবশ্যই প্রথমে একটি ডিওএম ট্রি তৈরি করতে হবে" এমন মন্তব্য সম্পর্কে: না, আপনার এটি করার দরকার নেই এবং করা উচিত নয়।

পরিবর্তে, একটি স্ট্রিমসোর্স তৈরি করুন (নতুন স্ট্রিমসোর্স (নতুন স্ট্রিংস রিডার (স্ট্র)) এবং উল্লিখিত পরিচয় ট্রান্সফর্মারটিকে এটি ফিড করুন That এটি স্যাক্স পার্সার ব্যবহার করবে, এবং ফলস্বরূপ আরও দ্রুত হবে thisএ ক্ষেত্রে মধ্যবর্তী গাছ তৈরি করা খাঁটি ওভারহেড। অন্যথায় শীর্ষস্থানীয় উত্তরটি ভাল।


1
আমি আন্তরিকভাবে একমত: মধ্যবর্তী ডিওএম গাছ তৈরি করা স্মৃতির অপচয়। এই উত্তরের জন্য থানস্ক।
ফ্লোরিয়ান এফ

9

স্কেল ব্যবহার:

import xml._
val xml = XML.loadString("<tag><nested>hello</nested></tag>")
val formatted = new PrettyPrinter(150, 2).format(xml)
println(formatted)

আপনি স্কেল-গ্রন্থাগার.জারের উপর নির্ভর করে আপনি জাভাতেও এটি করতে পারেন। দেখে মনে হচ্ছে:

import scala.xml.*;

public class FormatXML {
    public static void main(String[] args) {
        String unformattedXml = "<tag><nested>hello</nested></tag>";
        PrettyPrinter pp = new PrettyPrinter(150, 3);
        String formatted = pp.format(XML.loadString(unformattedXml), TopScope$.MODULE$);
        System.out.println(formatted);
    }
}

PrettyPrinterবস্তু দুটি ints, প্রথম হচ্ছে সর্বোচ্চ লাইন দৈর্ঘ্য এবং দ্বিতীয় খাঁজ পদক্ষেপ হচ্ছে নির্মাণ করা হয়।


9

মিলোস্মেন্স থেকে সামান্য উন্নত সংস্করণ ...

public static String getPrettyXml(String xml) {
    if (xml == null || xml.trim().length() == 0) return "";

    int stack = 0;
    StringBuilder pretty = new StringBuilder();
    String[] rows = xml.trim().replaceAll(">", ">\n").replaceAll("<", "\n<").split("\n");

    for (int i = 0; i < rows.length; i++) {
        if (rows[i] == null || rows[i].trim().length() == 0) continue;

        String row = rows[i].trim();
        if (row.startsWith("<?")) {
            pretty.append(row + "\n");
        } else if (row.startsWith("</")) {
            String indent = repeatString(--stack);
            pretty.append(indent + row + "\n");
        } else if (row.startsWith("<") && row.endsWith("/>") == false) {
            String indent = repeatString(stack++);
            pretty.append(indent + row + "\n");
            if (row.endsWith("]]>")) stack--;
        } else {
            String indent = repeatString(stack);
            pretty.append(indent + row + "\n");
        }
    }

    return pretty.toString().trim();
}

private static String repeatString(int stack) {
     StringBuilder indent = new StringBuilder();
     for (int i = 0; i < stack; i++) {
        indent.append(" ");
     }
     return indent.toString();
} 

রিপিটস্ট্রিং (স্ট্যাক ++) কোথায়; পদ্ধতি ..?
ব্যবহারকারী 1912935

2
প্রাইভেট স্ট্যাটিক স্ট্রিং রিপিট্রিং স্ট্রিং (ইন স্ট্যাক) {স্ট্রিংবিল্ডার ইনডেন্ট = নতুন স্ট্রিংবিল্ডার (); (int i = 0; i <stack; i ++) {indent.append ("") এর জন্য; } retent indent.toString (); }
কোডস্ক্র্যাপ

শেষ ট্যাগগুলিতে ইন্ডেন্টেশনটি ঠিকঠাক কাজ করছে না You } else if (row.startsWith("</")) {আপনাকে এই অংশটি পরিবর্তন করতে হবে :else if (row.startsWith("</")) { String indent = repeatIdent(--stack); if (pretty.charAt(pretty.length() - 1) == '\n') { pretty.append(indent + row + "\n"); } else { pretty.append(row + "\n"); } }
সিএসবা টেনস

8

কেবলমাত্র ভবিষ্যতের রেফারেন্সের জন্য, এখানে একটি সমাধান রয়েছে যা আমার পক্ষে কাজ করেছে (@ জর্জ হকিন্স উত্তরের একটিতে পোস্ট করেছেন এমন মন্তব্যের জন্য ধন্যবাদ):

DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
LSSerializer writer = impl.createLSSerializer();
writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
LSOutput output = impl.createLSOutput();
ByteArrayOutputStream out = new ByteArrayOutputStream();
output.setByteStream(out);
writer.write(document, output);
String xmlStr = new String(out.toByteArray());

6

আপনি যদি নিশ্চিত হন যে আপনার একটি বৈধ এক্সএমএল রয়েছে, তবে এটি সাধারণ, এবং এক্সএমএল ডোম গাছগুলি এড়িয়ে চলে। কিছু কিছু বাগ থাকতে পারে, যদি কিছু দেখতে পান তবে কমেন্ট করুন

public String prettyPrint(String xml) {
            if (xml == null || xml.trim().length() == 0) return "";

            int stack = 0;
            StringBuilder pretty = new StringBuilder();
            String[] rows = xml.trim().replaceAll(">", ">\n").replaceAll("<", "\n<").split("\n");

            for (int i = 0; i < rows.length; i++) {
                    if (rows[i] == null || rows[i].trim().length() == 0) continue;

                    String row = rows[i].trim();
                    if (row.startsWith("<?")) {
                            // xml version tag
                            pretty.append(row + "\n");
                    } else if (row.startsWith("</")) {
                            // closing tag
                            String indent = repeatString("    ", --stack);
                            pretty.append(indent + row + "\n");
                    } else if (row.startsWith("<")) {
                            // starting tag
                            String indent = repeatString("    ", stack++);
                            pretty.append(indent + row + "\n");
                    } else {
                            // tag data
                            String indent = repeatString("    ", stack);
                            pretty.append(indent + row + "\n");
                    }
            }

            return pretty.toString().trim();
    }

2
পুনরায় স্ট্রিং পদ্ধতিটি কোথায় ..?
ব্যবহারকারী 1912935

3
প্রাইভেট স্ট্যাটিক স্ট্রিং রিপিট্রিং স্ট্রিং (ইন স্ট্যাক) {স্ট্রিংবিল্ডার ইনডেন্ট = নতুন স্ট্রিংবিল্ডার (); (int i = 0; i <stack; i ++) {indent.append ("") এর জন্য; } retent indent.toString (); }
কোডস্ক্র্যাপ

হ্যাঁ [ব্যবহারকারী 1912935], @ কোডস্ক্র্যাপ যা লিখেছেন তা যথেষ্ট সহজ হওয়া উচিত :)
মিলোস্মেন্স

একটি লুপের অভ্যন্তরে স্ট্রিংবিল্ডারের সাথে সংঘর্ষ: খারাপ অনুশীলন।
james.garriss

@ জেমস.গরিসগুলি তবে নতুন লাইনে বিভক্ত হওয়া খুব সহজ, এটি কোনও ডোম গাছ ছাড়াই একটি সহজ পদ্ধতির চিত্রিত করে।
milosmns

5

উপরের সমস্ত সমাধান আমার পক্ষে কার্যকর হয়নি, তবে আমি এটি http://myshittycode.com/2014/02/10/java-properly-indenting-xml-string/ এ পেয়েছি

ক্লুটি এক্সপ্যাথের সাথে সাদা স্থানগুলি সরিয়ে ফেলবে

    String xml = "<root>" +
             "\n   " +
             "\n<name>Coco Puff</name>" +
             "\n        <total>10</total>    </root>";

try {
    Document document = DocumentBuilderFactory.newInstance()
            .newDocumentBuilder()
            .parse(new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8"))));

    XPath xPath = XPathFactory.newInstance().newXPath();
    NodeList nodeList = (NodeList) xPath.evaluate("//text()[normalize-space()='']",
                                                  document,
                                                  XPathConstants.NODESET);

    for (int i = 0; i < nodeList.getLength(); ++i) {
        Node node = nodeList.item(i);
        node.getParentNode().removeChild(node);
    }

    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

    StringWriter stringWriter = new StringWriter();
    StreamResult streamResult = new StreamResult(stringWriter);

    transformer.transform(new DOMSource(document), streamResult);

    System.out.println(stringWriter.toString());
}
catch (Exception e) {
    e.printStackTrace();
}

1
নোট করুন যে '{ xML.apache.org/xslt } ইনডেন্ট-পরিমাণ' সম্পত্তি ব্যবহার আপনাকে একটি নির্দিষ্ট ট্রান্সফর্মার বাস্তবায়নের সাথে আবদ্ধ করবে।
ভ্যালিওমোর্টিস

1
সমস্ত সমাধান থেকে এই এক ভাল কাজ করেছে। আমার এক্সএমএল এর মধ্যে ইতিমধ্যে আমার শূন্যস্থান এবং নতুন লাইন ছিল প্লাস আমি আমার প্রকল্পে আরও নির্ভরতা যুক্ত করতে চাইনি। আমি চাই এক্সএমএলটি পার্স করতে না পারলেও ওহ ভাল।
ফ্যাবিও

5

নিচের এই কোডটি নিখুঁতভাবে কাজ করছে

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

String formattedXml1 = prettyFormat("<root><child>aaa</child><child/></root>");

public static String prettyFormat(String input) {
    return prettyFormat(input, "2");
}

public static String prettyFormat(String input, String indent) {
    Source xmlInput = new StreamSource(new StringReader(input));
    StringWriter stringWriter = new StringWriter();
    try {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", indent);
        transformer.transform(xmlInput, new StreamResult(stringWriter));

        String pretty = stringWriter.toString();
        pretty = pretty.replace("\r\n", "\n");
        return pretty;              
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

5

আমি তাদের সব মিশ্রিত এবং একটি ছোট প্রোগ্রাম লিখছি। এটি এক্সএমএল ফাইল থেকে পড়ছে এবং মুদ্রণ করছে। Xzy এর পরিবর্তে আপনার ফাইলের পথ দিন।

    public static void main(String[] args) throws Exception {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setValidating(false);
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(new FileInputStream(new File("C:/Users/xyz.xml")));
    prettyPrint(doc);

}

private static String prettyPrint(Document document)
        throws TransformerException {
    TransformerFactory transformerFactory = TransformerFactory
            .newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    DOMSource source = new DOMSource(document);
    StringWriter strWriter = new StringWriter();
    StreamResult result = new StreamResult(strWriter);transformer.transform(source, result);
    System.out.println(strWriter.getBuffer().toString());

    return strWriter.getBuffer().toString();

}

4

আমাদের জন্য কাজ করে যা একটি মাত্র সমাধান

import java.io.StringWriter;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

**
 * Pretty Print XML String
 * 
 * @param inputXmlString
 * @return
 */
public static String prettyPrintXml(String xml) {

    final StringWriter sw;

    try {
        final OutputFormat format = OutputFormat.createPrettyPrint();
        final org.dom4j.Document document = DocumentHelper.parseText(xml);
        sw = new StringWriter();
        final XMLWriter writer = new XMLWriter(sw, format);
        writer.write(document);
    }
    catch (Exception e) {
        throw new RuntimeException("Error pretty printing xml:\n" + xml, e);
    }
    return sw.toString();
}

3

Jdom2 ব্যবহার: http://www.jdom.org/

import java.io.StringReader;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

String prettyXml = new XMLOutputter(Format.getPrettyFormat()).
                         outputString(new SAXBuilder().build(new StringReader(uglyXml)));

3

সর্বোচ্চ , কোডস্ক্র্যাপ , ডেভিড ইজলি এবং মিলোস্মেন্সের উত্তরগুলির বিকল্প হিসাবে আমার লাইটওয়েট, উচ্চ-পারফরম্যান্সের সুন্দর-প্রিন্টার লাইব্রেরিটি দেখুন: এক্সএমএল-ফর্ম্যাটার

// construct lightweight, threadsafe, instance
PrettyPrinter prettyPrinter = PrettyPrinterBuilder.newPrettyPrinter().build();

StringBuilder buffer = new StringBuilder();
String xml = ..; // also works with char[] or Reader

if(prettyPrinter.process(xml, buffer)) {
     // valid XML, print buffer
} else {
     // invalid XML, print xml
}

কখনও কখনও, যেমন ফাইল থেকে সরাসরি উপহাস এসওএপি পরিষেবাগুলি চালনার সময়, একটি সুন্দর-প্রিন্টার থাকা ভাল যা ইতিমধ্যে প্রি-প্রিন্টেড এক্সএমএলও পরিচালনা করে:

PrettyPrinter prettyPrinter = PrettyPrinterBuilder.newPrettyPrinter().ignoreWhitespace().build();

যেমন কিছু মন্তব্য করেছেন, চমত্কার-মুদ্রণটি আরও মানব-পঠনযোগ্য আকারে এক্সএমএল উপস্থাপনের একটি উপায় - সাদা স্থান স্পষ্টভাবে আপনার এক্সএমএল ডেটাতে অন্তর্ভুক্ত নয়।

লাইব্রেরিটি লগিংয়ের উদ্দেশ্যে প্রিন্ট-প্রিন্টিংয়ের উদ্দেশ্যে তৈরি এবং সিডিএটিএ এবং টেক্সট নোডগুলিতে ফিল্টারিং (সাবট্রি অপসারণ / বেনামে নামকরণ) এবং এক্সএমএল-এর প্রিন্ট-প্রিন্টিংয়ের জন্যও রয়েছে।


2

আমারও একই সমস্যা ছিল এবং আমি জেটিডি ( http://jtidy.sourceforge.net/index.html) এর সাথে দুর্দান্ত সাফল্য পাচ্ছি ) এর

উদাহরণ:

Tidy t = new Tidy();
t.setIndentContent(true);
Document d = t.parseDOM(
    new ByteArrayInputStream("HTML goes here", null);

OutputStream out = new ByteArrayOutputStream();
t.pprint(d, out);
String html = out.toString();

2

ইন্ডস্কোর-জাভা স্থির পদ্ধতি রয়েছে U.formatXml(string)। আমি প্রকল্পের রক্ষণাবেক্ষণকারী। সরাসরি উদাহরণ

import com.github.underscore.lodash.U;

public class MyClass {
    public static void main(String args[]) {
        String xml = "<tag><nested>hello</nested></tag>";

        System.out.println(U.formatXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>" + xml + "</root>"));
    }
}

আউটপুট:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <tag>
      <nested>hello</nested>
   </tag>
</root>

এটা সত্যিই দারুন!
সিনিয়র

1

xMLstarlet ( http://xMLstar.sourceforge.net/ ) নামে একটি খুব সুন্দর কমান্ড লাইন এক্সএমএল ইউটিলিটি রয়েছে যা প্রচুর লোক ব্যবহার করে যা অনেক কিছু করতে পারে।

আপনার রানটাইম.এক্সেক ব্যবহার করে এই প্রোগ্রামটি প্রোগ্রামাগতভাবে সম্পাদন করতে পারে এবং তারপরে ফর্ম্যাট করা আউটপুট ফাইলটি পুনরায় পড়া যায়। এটিতে জাভা কোডের কয়েকটি লাইন সরবরাহ করতে পারে তার চেয়ে আরও বিকল্প এবং আরও ভাল ত্রুটির প্রতিবেদন রয়েছে।

এক্সএমএম স্টারলেট ডাউনলোড করুন: http://sourceforge.net/project/showfiles.php?group_id=66612&package_id=64589


1

আমি দেখেছি যে জাভা ১.6.০_৩২ এ এক্সএমএল স্ট্রিং প্রিন্ট করার জন্য সাধারণ পদ্ধতি (নাল বা পরিচয় এক্সএসল্ট সহ ট্রান্সফর্মার ব্যবহার করা) আমি আচরণ করব না যেমন আমি চাই যে ট্যাগগুলি কেবল স্পেসস্পেস দ্বারা পৃথক করা হয়েছে, বিচ্ছেদ না করার বিপরীতে পাঠ্য। আমি <xsl:strip-space elements="*"/>আমার টেম্পলেটটিতে ব্যবহার করার চেষ্টা করেছি no আমার সর্বাধিক সহজ সমাধানটি হ'ল আমি স্যাক্সসোর্স এবং এক্সএমএল ফিল্টারটি যেভাবে চাইছিলাম সেভাবে স্থানটি ছিনিয়ে নেওয়া। যেহেতু আমার সমাধান লগিংয়ের জন্য ছিল তাই আমি এটিকে অসম্পূর্ণ এক্সএমএল টুকরা দিয়ে কাজ করতে প্রসারিত করেছি। নোট করুন যে আপনি যদি একটি ডিওএমএস উত্স ব্যবহার করেন তবে সাধারণ পদ্ধতিটি ঠিকঠাক হয়ে গেছে বলে মনে হচ্ছে তবে আমি অসম্পূর্ণতা এবং মেমরির ওভারহেডের কারণে এটি ব্যবহার করতে চাই নি।

public static class WhitespaceIgnoreFilter extends XMLFilterImpl
{

    @Override
    public void ignorableWhitespace(char[] arg0,
                                    int arg1,
                                    int arg2) throws SAXException
    {
        //Ignore it then...
    }

    @Override
    public void characters( char[] ch,
                            int start,
                            int length) throws SAXException
    {
        if (!new String(ch, start, length).trim().equals("")) 
               super.characters(ch, start, length); 
    }
}

public static String prettyXML(String logMsg, boolean allowBadlyFormedFragments) throws SAXException, IOException, TransformerException
    {
        TransformerFactory transFactory = TransformerFactory.newInstance();
        transFactory.setAttribute("indent-number", new Integer(2));
        Transformer transformer = transFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
        StringWriter out = new StringWriter();
        XMLReader masterParser = SAXHelper.getSAXParser(true);
        XMLFilter parser = new WhitespaceIgnoreFilter();
        parser.setParent(masterParser);

        if(allowBadlyFormedFragments)
        {
            transformer.setErrorListener(new ErrorListener()
            {
                @Override
                public void warning(TransformerException exception) throws TransformerException
                {
                }

                @Override
                public void fatalError(TransformerException exception) throws TransformerException
                {
                }

                @Override
                public void error(TransformerException exception) throws TransformerException
                {
                }
            });
        }

        try
        {
            transformer.transform(new SAXSource(parser, new InputSource(new StringReader(logMsg))), new StreamResult(out));
        }
        catch (TransformerException e)
        {
            if(e.getCause() != null && e.getCause() instanceof SAXParseException)
            {
                if(!allowBadlyFormedFragments || !"XML document structures must start and end within the same entity.".equals(e.getCause().getMessage()))
                {
                    throw e;
                }
            }
            else
            {
                throw e;
            }
        }
        out.flush();
        return out.toString();
    }

1

জাভা ১.6++ এর জন্য আমি এখানে যে সমাধানগুলি পেয়েছি সেগুলি কোডটি ইতিমধ্যে ফর্ম্যাট করা থাকলে পুনরায় ফর্ম্যাট করে না। আমার জন্য যে কাজ করেছে (এবং ইতিমধ্যে ফর্ম্যাট কোডটি পুনরায় ফর্ম্যাট করেছে) সেগুলি ছিল নিম্নলিখিত।

import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.w3c.dom.Element;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.io.StringReader;

public class XmlUtils {
    public static String toCanonicalXml(String xml) throws InvalidCanonicalizerException, ParserConfigurationException, SAXException, CanonicalizationException, IOException {
        Canonicalizer canon = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
        byte canonXmlBytes[] = canon.canonicalize(xml.getBytes());
        return new String(canonXmlBytes);
    }

    public static String prettyFormat(String input) throws TransformerException, ParserConfigurationException, IOException, SAXException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        InputSource src = new InputSource(new StringReader(input));
        Element document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(src).getDocumentElement();
        Boolean keepDeclaration = input.startsWith("<?xml");
        DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
        DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
        LSSerializer writer = impl.createLSSerializer();
        writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
        writer.getDomConfig().setParameter("xml-declaration", keepDeclaration);
        return writer.writeToString(document);
    }
}

সম্পূর্ণ স্ট্রিং এক্সএমএল তুলনার জন্য আপনার ইউনিট পরীক্ষায় এটি ব্যবহার করা ভাল সরঞ্জাম।

private void assertXMLEqual(String expected, String actual) throws ParserConfigurationException, IOException, SAXException, CanonicalizationException, InvalidCanonicalizerException, TransformerException, IllegalAccessException, ClassNotFoundException, InstantiationException {
    String canonicalExpected = prettyFormat(toCanonicalXml(expected));
    String canonicalActual = prettyFormat(toCanonicalXml(actual));
    assertEquals(canonicalExpected, canonicalActual);
}

1

দ্রুত এবং নোংরা সমাধানের জন্য যারা অনুসন্ধান করছেন - তাদের এক্সএমএল 100% বৈধ হওয়ার দরকার নেই। যেমন রেস্ট / এসওএপি লগিংয়ের ক্ষেত্রে (আপনি কখনই জানেন না যে অন্যরা কী পাঠায় ;-))

আমি অনলাইনে খুঁজে পেয়েছি এমন একটি কোড স্নিপড পেয়েছি এবং উন্নত করেছি যা আমি মনে করি যে এটি একটি বৈধ সম্ভাব্য পদ্ধতির হিসাবে এখানে এখনও অনুপস্থিত:

public static String prettyPrintXMLAsString(String xmlString) {
    /* Remove new lines */
    final String LINE_BREAK = "\n";
    xmlString = xmlString.replaceAll(LINE_BREAK, "");
    StringBuffer prettyPrintXml = new StringBuffer();
    /* Group the xml tags */
    Pattern pattern = Pattern.compile("(<[^/][^>]+>)?([^<]*)(</[^>]+>)?(<[^/][^>]+/>)?");
    Matcher matcher = pattern.matcher(xmlString);
    int tabCount = 0;
    while (matcher.find()) {
        String str1 = (null == matcher.group(1) || "null".equals(matcher.group())) ? "" : matcher.group(1);
        String str2 = (null == matcher.group(2) || "null".equals(matcher.group())) ? "" : matcher.group(2);
        String str3 = (null == matcher.group(3) || "null".equals(matcher.group())) ? "" : matcher.group(3);
        String str4 = (null == matcher.group(4) || "null".equals(matcher.group())) ? "" : matcher.group(4);

        if (matcher.group() != null && !matcher.group().trim().equals("")) {
            printTabs(tabCount, prettyPrintXml);
            if (!str1.equals("") && str3.equals("")) {
                ++tabCount;
            }
            if (str1.equals("") && !str3.equals("")) {
                --tabCount;
                prettyPrintXml.deleteCharAt(prettyPrintXml.length() - 1);
            }

            prettyPrintXml.append(str1);
            prettyPrintXml.append(str2);
            prettyPrintXml.append(str3);
            if (!str4.equals("")) {
                prettyPrintXml.append(LINE_BREAK);
                printTabs(tabCount, prettyPrintXml);
                prettyPrintXml.append(str4);
            }
            prettyPrintXml.append(LINE_BREAK);
        }
    }
    return prettyPrintXml.toString();
}

private static void printTabs(int count, StringBuffer stringBuffer) {
    for (int i = 0; i < count; i++) {
        stringBuffer.append("\t");
    }
}

public static void main(String[] args) {
    String x = new String(
            "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>INVALID_MESSAGE</faultstring><detail><ns3:XcbSoapFault xmlns=\"\" xmlns:ns3=\"http://www.someapp.eu/xcb/types/xcb/v1\"><CauseCode>20007</CauseCode><CauseText>INVALID_MESSAGE</CauseText><DebugInfo>Problems creating SAAJ object model</DebugInfo></ns3:XcbSoapFault></detail></soap:Fault></soap:Body></soap:Envelope>");
    System.out.println(prettyPrintXMLAsString(x));
}

এখানে ফলাফল:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <soap:Fault>
        <faultcode>soap:Client</faultcode>
        <faultstring>INVALID_MESSAGE</faultstring>
        <detail>
            <ns3:XcbSoapFault xmlns="" xmlns:ns3="http://www.someapp.eu/xcb/types/xcb/v1">
                <CauseCode>20007</CauseCode>
                <CauseText>INVALID_MESSAGE</CauseText>
                <DebugInfo>Problems creating SAAJ object model</DebugInfo>
            </ns3:XcbSoapFault>
        </detail>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

1

আমি একটি উত্তর ব্যবহার করে দেখেছি Scala, সুতরাং এখানে অন্যটি এখানে রয়েছে Groovy, কেবল যদি কেউ এটি আকর্ষণীয় মনে করে। ডিফল্ট ইনডেন্টেশন 2 পদক্ষেপ, XmlNodePrinterকনস্ট্রাক্টর পাশাপাশি অন্য মান পাস করা যেতে পারে।

def xml = "<tag><nested>hello</nested></tag>"
def stringWriter = new StringWriter()
def node = new XmlParser().parseText(xml);
new XmlNodePrinter(new PrintWriter(stringWriter)).print(node)
println stringWriter.toString()

গ্রোভি জার ক্লাসপথে থাকলে জাভা থেকে ব্যবহার

  String xml = "<tag><nested>hello</nested></tag>";
  StringWriter stringWriter = new StringWriter();
  Node node = new XmlParser().parseText(xml);
  new XmlNodePrinter(new PrintWriter(stringWriter)).print(node);
  System.out.println(stringWriter.toString());

1

যদি আপনার এডেন্টেশন প্রয়োজন না হয় তবে কয়েকটি লাইন ব্রেক হয়ে যায় তবে এটি কেবল রেইজেক্সের পক্ষে যথেষ্ট হতে পারে ...

String leastPrettifiedXml = uglyXml.replaceAll("><", ">\n<");

কোডটি দুর্দান্ত, ইন্ডেন্টেশন মিস করার কারণে ফলাফল নয়।


(ইনডেন্টেশন সহ সমাধানের জন্য, অন্যান্য উত্তর দেখুন))


1
হুমমমম ... শুধু জোরে ভাবছি, এরকম সমাধানের দরকার কার? আমি দেখতে পাচ্ছি কেবলমাত্র ক্ষেত্রটি হ'ল আমরা কিছু ওয়েব পরিষেবা থেকে প্রাপ্ত ডেটা এবং কেবলমাত্র সেই ডেটা এবং তার বৈধতা পরীক্ষা করতে, বিকাশকারী বা পরীক্ষককে এ জাতীয় সহজ জিনিসগুলির প্রয়োজন হতে পারে। নাহলে ভাল বিকল্প নয় ....
সুধাকর চাওয়ালি

1
@ সুধাকর চাবলি আমি বিকাশকারী। নোংরা প্রিন্টলন () এবং লগ.ডিবগ () হ্যাকের জন্য আমার এটি প্রয়োজন হতে পারে; উদাহরণস্বরূপ, কিছু সময় আমি প্রোগ্রামটি স্নেহ-ধাপে ধাপে ডিবাগিংয়ের পরিবর্তে কেবলমাত্র একটি সীমাবদ্ধ সার্ভার পরিবেশের (শেল অ্যাক্সেসের পরিবর্তে ওয়েব অ্যাডমিন ইন্টারফেস সহ) লগ ফাইলগুলি ব্যবহার করতে পারি।
কমোনেড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.