Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中使用StAX读取和修改XML片段?_Java_Xml_Dom_Stax - Fatal编程技术网

如何在Java中使用StAX读取和修改XML片段?

如何在Java中使用StAX读取和修改XML片段?,java,xml,dom,stax,Java,Xml,Dom,Stax,我的目标是将对象(featureMember)读入DOM,更改它们并写回新的XML。XML太大,无法使用DOM本身。我想我需要的是StAX和TransformerFactory,但我不能让它工作 这就是我到目前为止所做的: private void change(File pathIn, File pathOut) { try { XMLInputFactory factory = XMLInputFactory.newInstance(); XMLOu

我的目标是将对象(featureMember)读入DOM,更改它们并写回新的XML。XML太大,无法使用DOM本身。我想我需要的是StAX和TransformerFactory,但我不能让它工作

这就是我到目前为止所做的:

private void change(File pathIn, File pathOut) {
    try {

        XMLInputFactory factory = XMLInputFactory.newInstance();
        XMLOutputFactory factoryOut = XMLOutputFactory.newInstance();

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();

        XMLEventReader in = factory.createXMLEventReader(new FileReader(pathIn));
        XMLEventWriter out = factoryOut.createXMLEventWriter(new FileWriter(pathOut));

        while (in.hasNext()) {
            XMLEvent e = in.nextTag();
            if (e.getEventType() == XMLStreamConstants.START_ELEMENT) {
                if (((StartElement) e).getName().getLocalPart().equals("featureMember")) {
                    DOMResult result = new DOMResult();
                    t.transform(new StAXSource(in), result);
                    Node domNode = result.getNode();
                    System.out.println(domnode);
                }
            }
            out.add(e);
        }
        in.close();
        out.close();

    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    } catch (IOException e1) {
        e1.printStackTrace();
    } catch (TransformerConfigurationException e1) {
        e1.printStackTrace();
    } catch (XMLStreamException e1) {
        e1.printStackTrace();
    } catch (TransformerException e1) {
        e1.printStackTrace();
    }
}
我得到异常(在t.transform()上):

我的xml的简化版本如下(它有名称空间):


克拉科夫
id1234
1002
热舒夫
id1235
我有一个对象(featureMember)的localId列表,我想更改这些对象,并对更改的RST或pole进行相应的编码(这取决于更改的用户):

本地(id1234)RST(1001)

本地(id1236)RST(1003)


您遇到的问题是,当您创建
statxSource
时,您的START\u元素事件已被使用。因此,
XMLEventReader
可能在某个空白文本节点事件中,或者在其他不能作为XML文档源的事件中。您可以使用
peek()
方法查看下一个事件而不使用它。不过,请确保有一个事件是以
hasNext()
开头的

我不能百分之百确定您希望完成什么,因此根据具体情况,您可以做一些事情

编辑:我刚刚读了一些关于你问题的评论,这些评论让事情变得更清楚了。下面的内容仍然可以帮助您通过一些调整来实现所需的结果。还要注意,JavaXSLT处理器允许扩展函数和扩展元素,它们可以从XSLT样式表调用Java代码。这是一种使用外部资源(如数据库查询)扩展基本XSLT功能的强大方法


如果希望将输入XML转换为一个输出XML,那么最好只使用XML样式表转换。在代码中,您创建了一个没有任何模板的转换器,因此它成为默认的“标识转换器”,只将输入复制到输出。假设您的输入XML如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml/3.2" gml:id="featureCollection" xmlns:eg="acme.com">
  <gml:featureMember>
    <eg:RST/>
    <eg:pole>Krakow</eg:pole>
    <eg:localId>id1234</eg:localId>
  </gml:featureMember>
  <gml:featureMember>
    <eg:RST>1002</eg:RST>
    <eg:pole>Rzeszow</eg:pole>
    <eg:localId>id1235</eg:localId>
  </gml:featureMember>
</gml:FeatureCollection>
这里是一个示例stylesheet.xsl文件,为了方便起见,我刚刚将其转储到与输入XML和类相同的包中

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:eg="acme.com">

    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="gml:featureMember">
        <gml:member>
            <xsl:apply-templates select="node()|@*" />
        </gml:member>
    </xsl:template>

</xsl:stylesheet>

您是否考虑过使用saxonica.com上Saxon 9 EE支持的流式XSLT 3.0解决这个问题?如果您编辑您的问题,并向我们展示您希望在
featureMember
元素上实现的更改,以及您是否希望为所有更改的元素生成一个结果,或者为每个更改的元素生成一个新文档,那么我可以向您展示如何以声明的方式使用XSLT 3.0实现这一点。我对XSLT 3.0一无所知,所以我没有考虑。我真的说不出我想要在
featureMember
元素上更改什么-这取决于用户(这就是我在这里需要DOM的原因)。我必须通过它的localID找到特定的
featureMember
,并更改它的一些元素。我有一个表,其中有我想要做的更改(它们并不总是相同的)。我想用所有更改的元素生成一个结果。是的,我很感兴趣。我已经设法做到了(它可以工作,但有点太慢了——每个文件1小时)。如果它真的更有效,我可以使用一些帮助。好的,我将提交一个代码示例,这是有帮助的,但我不确定它是否解决了我的问题。我必须更改每个featureMember-首先检查localId,然后更改其余属性。样式表可以这样做吗?StAX的问题是它只能继续前进。lokalId可以位于featureMember的末尾,因此当事件发生时,我无法更改以前的元素。@sophiess XSLT在这种情况下是否易于使用在某种程度上取决于您计划如何使用该ID。如果转换仅取决于ID和XML中包含的其他信息,那么XSLT就可以了。如果你必须利用外部资源,这将变得更加困难,可能不是最好的选择。看看样式表转换可以做些什么。如果你陷入困境,你可以在这里问一个与他们相关的问题,或者搜索类似的问题。
<?xml version="1.0" encoding="UTF-8"?>
<gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml/3.2" gml:id="featureCollection" xmlns:eg="acme.com">
  <gml:featureMember>
    <eg:RST/>
    <eg:pole>Krakow</eg:pole>
    <eg:localId>id1234</eg:localId>
  </gml:featureMember>
  <gml:featureMember>
    <eg:RST>1002</eg:RST>
    <eg:pole>Rzeszow</eg:pole>
    <eg:localId>id1235</eg:localId>
  </gml:featureMember>
</gml:FeatureCollection>
package xsltplayground;

import java.io.File;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class XSLTplayground {

    public static void main(String[] args) throws Exception {

        URL url = XSLTplayground.class.getResource("sample.xml");
        File input = new File(url.toURI());
        URL url2 = XSLTplayground.class.getResource("stylesheet.xsl");
        File xslt = new File(url2.toURI());
        URL url3 = XSLTplayground.class.getResource(".");
        File output = new File(new File(url3.toURI()), "output.xml");
        change(input, output, xslt);

    }

    private static void change(File pathIn, File pathOut, File xsltFile) {
        try {

            // Creating transformer with XSLT file
            TransformerFactory tf = TransformerFactory.newInstance();
            Source xsltSource = new StreamSource(xsltFile);
            Transformer t = tf.newTransformer(xsltSource);

            // Input source
            Source input = new StreamSource(pathIn);

            // Output target
            Result output = new StreamResult(pathOut);

            // Transforming
            t.transform(input, output);

        } catch (TransformerConfigurationException ex) {
            Logger.getLogger(XSLTplayground.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(XSLTplayground.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:eg="acme.com">

    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="gml:featureMember">
        <gml:member>
            <xsl:apply-templates select="node()|@*" />
        </gml:member>
    </xsl:template>

</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<gml:FeatureCollection xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:eg="acme.com" gml:id="featureCollection">
  <gml:member>
    <eg:RST/>
    <eg:pole>Krakow</eg:pole>
    <eg:localId>id1234</eg:localId>
  </gml:member>
  <gml:member>
    <eg:RST>1002</eg:RST>
    <eg:pole>Rzeszow</eg:pole>
    <eg:localId>id1235</eg:localId>
  </gml:member>
</gml:FeatureCollection>
package xsltplayground;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import javax.xml.transform.stream.StreamSource;

public class XSLTplayground {

    public static void main(String[] args) throws Exception {

        URL url = XSLTplayground.class.getResource("sample.xml");
        File input = new File(url.toURI());
        URL url2 = XSLTplayground.class.getResource("stylesheet.xsl");
        File xslt = new File(url2.toURI());
        URL url3 = XSLTplayground.class.getResource(".");
        File output = new File(url3.toURI());
        change(input, output, xslt);

    }

    private static void change(File pathIn, File directoryOut, File xsltFile) throws InterruptedException {
        try {

            // Creating a StAX event reader from the input
            XMLInputFactory xmlIf = XMLInputFactory.newFactory();
            XMLEventReader reader = xmlIf.createXMLEventReader(new StreamSource(pathIn));

            // Create a StAX output factory
            XMLOutputFactory xmlOf = XMLOutputFactory.newInstance();

            int counter = 1;
            // Keep going until no more events
            while (reader.hasNext()) {
                // Peek into the next event to find out what it is
                XMLEvent next = reader.peek();
                // If it's the start of a featureMember element, commence output
                if (next.isStartElement() 
                        && next.asStartElement().getName().getLocalPart().equals("featureMember")) {
                    File output = new File(directoryOut, "output_" + counter + ".xml");
                    try (OutputStream ops = new FileOutputStream(output)) {
                        XMLEventWriter writer = xmlOf.createXMLEventWriter(ops);
                        copy(reader, writer);
                        writer.flush();
                        writer.close();
                    }
                    counter++;
                } else {
                    // Not in a featureMember element: ignore
                    reader.next();
                }
            }

        } catch (XMLStreamException ex) {
            Logger.getLogger(XSLTplayground.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(XSLTplayground.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }

    private static void copy(XMLEventReader reader, XMLEventWriter writer) throws XMLStreamException {

        // Creating an XMLEventFactory
        XMLEventFactory ef = XMLEventFactory.newFactory();
        // Writing an XML document start
        writer.add(ef.createStartDocument());

        int depth = 0;
        boolean stop = false;
        while (!stop) {
            XMLEvent next = reader.nextEvent();
            writer.add(next);
            if (next.isStartElement()) {
                depth++;
            } else if (next.isEndElement()) {
                depth--;
                if (depth == 0) {
                    writer.add(ef.createEndDocument());
                    stop = true;
                }
            }
        }

    }

}