当前位置: 首页 > 知识库问答 >
问题:

Java:如何使用父节点将XML流拆分为小型XML文档。VTD-XML

盖博简
2023-03-14

我需要使用VTD XML和XPath读取一个大xml并在多个节点中拆分结果。我在这里找到了一些解决方案,但它拆分了节点,但没有父级信息。

我为什么要找:

XPath string: /CATALOG/MAIN/CD基于XPath的文档应该拆分

1) 初始文件:

<代码>

2) 结果:文件1:

<代码>

文件2:

<代码>

文件3:

<代码>

感谢您的时间和建议。

顺致敬意,

共有3个答案

魏襦宗
2023-03-14

我解决了我的问题。下面是我基于标准SAX解析的方法。

1) 已创建自定义SaxHandler:

`公共类CustomSAXHandler扩展了DefaultHandler{

private Stack<XmlNodeInfo> nodeStack = new Stack<XmlNodeInfo>();
private List<String> xPaths;
private XmlNodeInfo rootNode;
private final NamespaceContext namespaceContext;
private List<XmlNodeInfo> resultNodes;

public CustomSAXHandler(String xpath, XmlNodeInfo rootNode, NamespaceContext namespaceContext) {
    this.rootNode = rootNode;
    this.namespaceContext = namespaceContext;
    resultNodes = new ArrayList<XmlNodeInfo>();
    xPaths = splitXpaths(xpath);
}

@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    String element = "<" + qName + getAttributes(atts) + ">";
    if (!nodeStack.empty()) {
        rootNode = nodeStack.peek();
    }

    if (matchDefinedXpath(qName)) {
        XmlNodeInfo newNode = new XmlNodeInfo(qName);
        rootNode.addChild(newNode);
        nodeStack.push(newNode);

        newNode.getHeader().append(element);
    } else {
        if (!nodeStack.empty()) {
            nodeStack.peek().getBody().append(element);
        }
    }
}

@Override
public void characters(char[] ch, int start, int length) throws SAXException {
    XmlNodeInfo currentNode = nodeStack.empty() ? null : nodeStack.peek();
    if (currentNode != null) {
        currentNode.getBody().append(new String(ch, start, length));
    }
}

@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
    String finalElement = xPaths.get(xPaths.size() - 1);
    String element = "</" + qName + ">";
    XmlNodeInfo currentNode = nodeStack.empty() ? null : nodeStack.peek();
    if (currentNode != null) {
        if (qName.equals(finalElement) && nodeStack.size() == xPaths.size()) {
            currentNode.getFooter().append(element);
            resultNodes.add(currentNode);
            nodeStack.pop();
        } else {
            if (currentNode.getName().equals(qName)) {
                currentNode.getFooter().append(element);
                nodeStack.pop();
            } else {
                currentNode.getBody().append(element);
            }
        }
    }
}

public List<String> getResults() {
    List<String> results = new ArrayList<String>();

    for (XmlNodeInfo node : resultNodes) {
        buildDocument(node, null, results);
    }

    return results;
}

private void buildDocument(XmlNodeInfo node, String childContent, List<String> results) {
    String body = node.getBody().toString();
    if (childContent != null) {
        body = body + childContent;
    }
    if (node.getParent() != null && !node.getParent().getName().equals(XmlNodeInfo.ROOT_NODE_NAME)) {
        String xmlContent = String.valueOf(node.getHeader()) + body + node.getFooter();
        buildDocument(node.getParent(), xmlContent, results);
    } else if (node.getParent() != null && node.getParent().getName().equals(XmlNodeInfo.ROOT_NODE_NAME)) {
        String finalContent = String.valueOf(node.getHeader()) + body + node.getFooter();
        results.add(finalContent);
    }
}

private String getAttributes(Attributes atts) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < atts.getLength(); i++) {
        String qName = atts.getQName(i);
        String value = atts.getValue(qName);
        builder.append(" ").append(qName).append("=").append("\"").append(value).append("\"");
    }
    return builder.toString();
}

private boolean matchDefinedXpath(String nodeName) {
    String[] splitWords = nodeName.split(":");
    if (splitWords.length == 2) {
        String namespacePrefix = splitWords[0];
        String namespaceURI = namespaceContext.getNamespaceURI(namespacePrefix);
        Iterator prefixes = namespaceContext.getPrefixes(namespaceURI);
        while (prefixes.hasNext()) {
            String prefix = (String) prefixes.next();
            String elementName = prefix + ":" + splitWords[1];
            if (xPaths.contains(elementName)) {
                return true;
            }
        }
    } else {
        return xPaths.contains(nodeName);
    }
    return false;
}

private List<String> splitXpaths(String xPath) {
    if (StringUtils.isNotBlank(xPath)) {
        String[] splitWords = xPath.split("/");
        if (splitWords.length > 0) {
            List<String> results = new ArrayList<String>();
            for (String splitWord : splitWords) {
                if(StringUtils.isNotBlank(splitWord)){
                    results.add(splitWord);
                }
            }
            return results;
        }
    }
    return null;
}

}

`

2)创建一个bean来存储节点数据:

`

公共类XmlNodeInfo{

public static final String ROOT_NODE_NAME = "ROOT";

private String name;
private StringBuilder header;
private StringBuilder body;
private StringBuilder footer;
private List<XmlNodeInfo> children;
private XmlNodeInfo parent;

public XmlNodeInfo(String name) {
    this.name = name;
    header = new StringBuilder();
    body = new StringBuilder();
    footer = new StringBuilder();
    children = new ArrayList<XmlNodeInfo>();
}

public StringBuilder getHeader() {
    return header;
}

public StringBuilder getBody() {
    return body;
}

public StringBuilder getFooter() {
    return footer;
}

public List<XmlNodeInfo> getChildren() {
    return children;
}

public void addChild(XmlNodeInfo xmlNodeInfo) {
    children.add(xmlNodeInfo);
    xmlNodeInfo.setParent(this);
}

public String getName() {
    return name;
}

public XmlNodeInfo getParent() {
    return parent;
}

public void setParent(XmlNodeInfo parent) {
    this.parent = parent;
}

}

`

3)运行程序:

'公共类MainApp{

public static void main(String[] args) throws Exception {
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser saxParser = factory.newSAXParser();

    NamespaceContext namespaceContext = new XmlNamespaceResolver();
    String xPath = "/CATALOG/MAIN/CD";

    InputStream in = MainApp.class.getClassLoader().getResourceAsStream("test.xml");
    XmlNodeInfo rootNode = new XmlNodeInfo(XmlNodeInfo.ROOT_NODE_NAME);
    CustomSAXHandler customSAXHandler = new CustomSAXHandler(xPath, rootNode, namespaceContext);
    saxParser.parse(in, customSAXHandler);
    List<String> results = customSAXHandler.getResults(); // result strings
}

}

`

也许不是最好的解决办法,但它解决了我的问题。谢谢大家的时间和建议。

浦思源
2023-03-14

Herez我的方法...

使用一些xml解析库,例如javax。xml。解析器。DocumentBuilderFactory为输入xml文件创建DOM。。。对于遇到的每个节点,创建一个新的输出文件文档。xml,例如Document1。xml(将子节点添加到父节点下。

您可以参考http://www.programcreek.com/java-api-examples/index.php?api=javax.xml.parsers.DocumentBuilderFactory获取使用java解析xml的示例java代码。xml。解析器。*软件包(查找加载问题示例)

魏毅
2023-03-14

下面是执行您在vtd-xml中描述的代码。如果有任何问题,请告诉我。

import com.ximpleware.*;
import java.io.FileOutputStream;

public class splitTest {

    public static void  main(String[] a) throws VTDException,java.io.IOException{
        VTDGen vg = new VTDGen();
        if (vg.parseFile("C:\\Users\\Jimmy Zhang\\workspace\\ximple-dev\\DOMTest\\test111.xml", false)){
            VTDNav vn = vg.getNav();
            AutoPilot ap = new AutoPilot(vn);
            ap.selectXPath("/CATALOG/MAIN");
            byte[] header = "<CATALOG>".getBytes();
            byte[] tail = "</CATALOG>".getBytes();
            int i = -1,j=0;
            while((i=ap.evalXPath())!=-1){
                long l = vn.getElementFragment();
                FileOutputStream fops = new FileOutputStream("c:\\xml\\output"+j+".xml");
                fops.write(header);
                fops.write(vn.getXML().getBytes(), (int)l, ((int)(l>>32)));
                fops.write(tail);
                fops.close();
                j++;
            }

        }
    }
}
 类似资料:
  • 我正在开发一个小程序,将一个非常大的XML文件(超过2Gb)分成小块。 在研究了许多库之后,我选择了VTD-XML(对大文件使用VTDGenHuge),并开始开发一些代码测试。但我在读取文件的段字节时遇到了一个问题。 我得到抵消和长度: 然后我得到结果信息: 最后,我尝试提取字节段以将其写入另一个文件: 但我正在学习java。lang.IndexOutOfBoundsException 此外,当我

  • 我想把大的xml分成小块。我正在使用VTDGen将xml文件分割成小块,它可以很好地适应文件大小 代码可以很好地使用VTDGen,但当我使用vtdgenhug时,它就不工作了。 我在“byte[]xml=vn.getXML().getBytes();”处得到空值当您执行syso vn时。getXML()获取对象值。但使用“getBytes()”返回null。我不知道为什么。但如果u do“byte

  • 我对如何做到这一点有点困惑,所有的文档/示例都展示了如何读取和编辑xml文档,但似乎没有任何从头开始创建xml的明确方法,我宁愿不必将我的程序与虚拟xml文件一起发布以编辑一个。有什么想法吗?谢谢。

  • 问题内容: 我有一个XML文件(在左侧),我想创建多个文件(在右侧): 我试图从原始XML文件中获取第一个子节点,并将其添加到新的子节点,但是在替换节点时,我一直遇到错误。 我想做类似以下的事情 但我得到一个错误 指出正确方向的任何帮助表示赞赏! 问题答案: 根据Java文档, 使用cloneNode方法。 摘要: 返回此节点的副本,即用作节点的通用副本构造函数。复制节点没有父节点。(parent

  • 问题内容: 我只需要此XML的HEADLINE,仅在标记之间。还必须连续不断地打印消息。我怎样才能做到这一点。 问题答案: 我将为此使用javax.xml.xpathJava SE 5中包含的API。

  • 我有两个xml文件。一个是参考(旧)文件,另一个是测试(新)文件。根据提供给我的一些规则,我必须检查是否有东西从旧模型中删除,然后添加到新模型中,或者检查是否有东西从旧文件中删除到新文件中。 我使用的是VTD-XML,但DOM解决方案或任何其他与xpath一起使用的解决方案将非常有用。 这是java代码: 1) 在ref文件上完成xpath后,我得到man节点的所有属性: 我得到name属性的值。