首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么xml文件在使用java在文件的开头和结尾追加字符串后没有正确对齐?

为什么xml文件在使用java在文件的开头和结尾追加字符串后没有正确对齐?
EN

Stack Overflow用户
提问于 2016-09-02 14:18:19
回答 2查看 949关注 0票数 2

我已经在XML的开头和结尾添加了字符串,在得到结果之后,对齐是不合适的。

我的XML文件:

代码语言:javascript
复制
        import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import com.google.common.io.Resources;

import java.io.StringReader;
import java.io.StringWriter;
import java.net.URL;
import java.nio.charset.Charset;

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

public class ModifyXMLFile {

    public static void main(String args[]) {

        try {
            // Point the file directory path here
            String directory = "C:\\Users\\n444479\\Desktop\\SA";
            int test = new File("C:\\Users\\n444479\\Desktop\\SA").listFiles().length;
            File[] files = new File(directory).listFiles();

            // Loop the file to run all the XML files
            for (int j = 0; j < test; j++) {
                System.out.println(files[j]);

                String filepathext = files[j].toString();

                DocumentBuilderFactory docFactory = DocumentBuilderFactory
                        .newInstance();
                DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
                Document doc = docBuilder.parse(filepathext);

                /*
                // XML file update starts here

                // 1.Add the attribute element with value between the two XML
                // Child elements



                 NodeList nodes = doc.getElementsByTagName("dummySegmentOne");
                 Text a = doc.createTextNode("value"); Element p =
                 doc.createElement("newNode"); p.appendChild(a);
                 nodes.item(0).getParentNode().insertBefore(p, nodes.item(0));


                // 2.Add the attribute element without value between the two XML
                // Child elements


                 NodeList nodesa =
                 doc.getElementsByTagName("customerLevelRegDocs"); Element q =
                 doc.createElement("dummySegmentOne");
                 nodesa.item(0).getParentNode().insertBefore(q,
                 nodesa.item(0));


                // 3.Rename the element in parent and child both using the JAXP
                // Parser
                */
                // XSLT File:

                String xsltResource = "C:\\Users\\n444479\\Desktop\\AB\\test.xml";

                StringWriter xmlResultResource = new StringWriter();

                Transformer xmlTransformer = TransformerFactory.newInstance().newTransformer(
                                new StreamSource(new File(xsltResource)));
                xmlTransformer.transform(new StreamSource(new File(filepathext)),new StreamResult(xmlResultResource));

                // XML file update end here

                // write the content into XML file
                TransformerFactory transformerFactory = TransformerFactory
                        .newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                DOMSource source = new DOMSource(doc);
                StreamResult result = new StreamResult(new String(filepathext));
                transformer.transform(source, result);
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
                // Successful output once get it "Done"
                String output = xmlResultResource.getBuffer().toString();
                // Writing the transformed XML to a file
                FileWriter fileWriter = new FileWriter(filepathext);
                fileWriter.write(output);
                fileWriter.close();

                System.out.println("Done");

            }
        }
        // Exception handling
        catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (TransformerException tfe) {
            tfe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (SAXException sae) {
            sae.printStackTrace();
        }
    }

}

一旦程序执行,字符串就会被正确地追加,但是XML文件对齐方式改变了。

我得到的输出如下

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>{% from lxml import etree %}{% from StringIO import StringIO %}{% set tree = parse_xml(request_text) %}{% set namespaces = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',  'wbs': 'http://xml.ama.com/ws/2009/01/WBS_Session-2.0.xsd'}%}<soap:Envelope xmlns:xalan="http://xml.apache.org/xalan" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><Session><SessionId>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SessionId', namespaces=namespaces)[0].text}}</SessionId><SequenceNumber>{{int(tree.xpath('//soapenv:Header/wbs:Session/wbs:SequenceNumber', namespaces=namespaces)[0].text)+1}}</SequenceNumber><SecurityToken>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SecurityToken', namespaces=namespaces)[0].text}}</SecurityToken></Session></soap:Header><soap:Body><reRoot><reNode> world</reNode></reRoot></soap:Body></soap:Envelope>

为什么文件没有被附加

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-09-02 14:53:19

原因是DataInputStream.readLine丢弃了换行符。所以,你得自己加上去。

此外:考虑到生成的XML是不正确的,因为原来的XML头最终包含在一个节点中。标头(如果存在)必须始终在根节点之前。

为了正确地将输入XML转换为SOAP,我推荐两种选择:

  • 要么通过XSL样式表来转换它。
  • 或者使用DOM构建生成的XML,并将源XML作为一个子节点。然后,在序列化整个文档时,可以指定缩进参数。

更新

我建议你这个XSL:

代码语言:javascript
复制
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" version="1.0" encoding="UTF-8"/>

<xsl:strip-space elements="*"/>

<xsl:template match="/">{% from lxml import etree %}{% from StringIO import StringIO %}{% set tree = parse_xml(request_text) %}{% set namespaces = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',  'wbs': 'http://xml.ama.com/ws/2009/01/WBS_Session-2.0.xsd'}%}<soap:Envelope xmlns:xalan="http://xml.apache.org/xalan" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <Session>
      <SessionId>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SessionId', namespaces=namespaces)[0].text}}</SessionId>
      <SequenceNumber>{{int(tree.xpath('//soapenv:Header/wbs:Session/wbs:SequenceNumber', namespaces=namespaces)[0].text)+1}}</SequenceNumber>
      <SecurityToken>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SecurityToken', namespaces=namespaces)[0].text}}</SecurityToken>
    </Session>
  </soap:Header>
  <soap:Body><xsl:copy-of select="."/>
</soap:Body>
</soap:Envelope>
</xsl:template>

</xsl:stylesheet>

换句话说:它创建一个固定格式的SOAP消息,并将输入的xml设置为<soap:Body>节点的内容。

以及转换代码:

代码语言:javascript
复制
private static void transform(org.w3c.dom.Document doc, java.io.InputStream inputXsl, java.io.OutputStream out)
    throws java.io.IOException,
    javax.xml.transform.TransformerConfigurationException,
    javax.xml.transform.TransformerException
{
    javax.xml.transform.Templates templates=javax.xml.transform.TransformerFactory.newInstance().newTemplates(new javax.xml.transform.stream.StreamSource(inputXsl));
    javax.xml.transform.Transformer transformer=templates.newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    javax.xml.transform.Result result=new javax.xml.transform.stream.StreamResult(out);
    javax.xml.transform.Source source=new javax.xml.transform.dom.DOMSource(doc);
    if (doc.getInputEncoding() != null)
    {
        transformer.setOutputProperty("encoding", doc.getInputEncoding());
    }
    transformer.transform(source, result);
}

整个结果由两个原因重新缩进:

  • XSL中的xsl:strip-space
  • 转换中的indentindent-amount属性。
票数 1
EN

Stack Overflow用户

发布于 2016-09-06 08:16:57

下面的XSL样式表将正确地格式化xml

代码语言:javascript
复制
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="/">
{% from lxml import etree %}{% from StringIO import StringIO %}{% set tree = parse_xml(request_text) %}{% set namespaces = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',  'wbs': 'http://xml.ama.com/ws/2009/01/WBS_Session-2.0.xsd'}%}
<soap:Envelope xmlns:xalan="http://xml.apache.org/xalan" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <Session>
      <SessionId>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SessionId', namespaces=namespaces)[0].text}}</SessionId>
      <SequenceNumber>{{int(tree.xpath('//soapenv:Header/wbs:Session/wbs:SequenceNumber', namespaces=namespaces)[0].text)+1}}</SequenceNumber>
      <SecurityToken>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SecurityToken', namespaces=namespaces)[0].text}}</SecurityToken>
    </Session>
  </soap:Header>
  <soap:Body><xsl:copy-of select="."/>
</soap:Body>
</soap:Envelope>
</xsl:template>

</xsl:stylesheet>

@小桑蒂,谢谢你帮助我,让我明白一些事情。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39294618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档