【问题标题】:How do I print out just certain elements from a text file that has xml tags to a new text file?如何将具有 xml 标签的文本文件中的某些元素打印到新的文本文件中?
【发布时间】:2014-08-08 02:08:05
【问题描述】:

我需要一些听起来很简单但给我带来麻烦的帮助。

我有一个文本文件 (record.txt),其中包含一个根元素“PatientRecord”和重复的子标签(“名字”、“年龄”、血型、地址等...)但具有不同的价值,因为它是每个人的记录。我只对将标签之间的值打印到每个人的新文本文件感兴趣,但只对我想要的元素感兴趣。例如,对于我上面提到的标签,我只需要姓名和年龄,而不需要该患者的其余信息。如何仅打印出用逗号分隔的值,然后转到下一位患者? 这是我到目前为止的代码

    package patient.records;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class ProcessRecords {
private static final String FILE = "C:\\Users\\Desktop\\records.txt";
private static final String RECORD_START_TAG = "<PatientRecord>";
private static final String RECORD_END_TAG = "</PatientRecord>"; 
private static final String newFileName = "C:\\Users\\Desktop\\DataFolder\\";    
public static void main(String[] args) throws Exception {
    String scan;    
    FileReader file = new FileReader(FILE);
    BufferedReader br = new BufferedReader(file);
    Writer writer = null;

    while ((scan = br.readLine()) != null)        
    {            
        if (scan.contains(RECORD_START_TAG)) { 


            //This is the logic I am missing that will only grab the element values
            //between the tags inside of the file

            writer = new BufferedWriter(new OutputStreamWriter(
            new FileOutputStream(newFileName + "Record Data" + ".txt"), "utf-8"));             
            }      
        else if (scan.contains(RECORD_END_TAG)) {
            writer.close();
            writer=null;
        }
        else {
            // only write if writer is not null
           if (writer!=null) {
            writer.write(scan);
           }
        }            
    }       
    br.close();
    }   
}   //This is the end of my code             

我正在阅读的文本文件 (record.txt) 如下所示:

<PatientRecord> <---first patient record--->
<---XML Schema goes here--->
            <Info>
                <age>66</age>
                <first_name>john</first_name>
                <last_name>smith</last_name>
                <mailing_address>200 main street</mailing_address>
                <blood_type>AB</blood_type>
                <phone_number>000-000-0000</phone_number>
</PatientRecord>
<PatientRecord> <---second patient record--->
<---XML Schema goes here--->
            <Info>
                <age>27</age>
                <first_name>micheal</first_name>
                <last_name>thompson</last_name>
                <mailing_address>123 baker street</mailing_address>
                <blood_type>O</blood_type>
                <phone_number>111-222-3333</phone_number>
</PatientRecord>

所以理论上,如果我只想从这个文本文件中为所有患者打印出标签中的名字、邮寄地址和血型的值,它应该如下所示:

john, 200 main street, AB
//this line is blank
michael, 123 baker street, O

感谢您的任何帮助。如果您觉得我的代码应该修改,那么我完全赞成。谢谢。

【问题讨论】:

  • 文本是这样混合内容还是被父标签包裹?

标签: java xml text output


【解决方案1】:

我的第一个直觉是将整个文本内容包装在一些外部标签周围并将文本处理为 XML,类似于...

<Patients>
    <PatientRecord> <---first patient record--->
        <Info>
            <age>66</age>
            <first_name>john</first_name>
            <last_name>smith</last_name>
            <mailing_address>200 main street</mailing_address>
            <blood_type>AB</blood_type>
            <phone_number>000-000-0000</phone_number>
    </PatientRecord>
    ...
</Patients>

但是这样做有两个问题……

一个&lt;---first patient record---&gt; 不是有效的XML 注释或文本,两个没有关闭&lt;/Info&gt; 标记...[叹气]

所以,我的下一个想法是,将每个 &lt;PatientRecord&gt; 个人作为文本读取,然后将其处理为 XML....

问题来了...我们需要删除任何被&lt;--- ... ---&gt;包围的东西,包括小箭头...对此有很多假设,但希望我们可以忽略它...

接下来的问题是,我们需要插入一个结束&lt;/Info&gt;标签...

之后,一切都变得非常简单......

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class Test {

    private static final String RECORD_START_TAG = "<PatientRecord>";
    private static final String RECORD_END_TAG = "</PatientRecord>";

    public static void main(String[] args) {
        File records = new File("Records.txt");
        try (BufferedReader br = new BufferedReader(new FileReader(records))) {
            StringBuilder record = null;
            String text = null;
            while ((text = br.readLine()) != null) {

                if (text.contains("<---") && text.contains("--->")) {
                    String start = text.substring(0, text.indexOf("<---"));
                    String end = text.substring(text.indexOf("--->") + 4);
                    text = start + end;
                }

                if (text.trim().length() > 0) {
                    if (text.startsWith(RECORD_START_TAG)) {

                        record = new StringBuilder(128);
                        record.append(text);

                    } else if (text.startsWith(RECORD_END_TAG)) {

                        record.append("</Info>");
                        record.append(text);

                        try (ByteArrayInputStream bais = new ByteArrayInputStream(record.toString().getBytes())) {

                            Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bais);
                            XPath xPath = XPathFactory.newInstance().newXPath();
                            XPathExpression exp = xPath.compile("PatientRecord/Info/first_name");
                            Node firstName = (Node) exp.evaluate(doc, XPathConstants.NODE);

                            exp = xPath.compile("PatientRecord/Info/mailing_address");
                            Node address = (Node) exp.evaluate(doc, XPathConstants.NODE);

                            exp = xPath.compile("PatientRecord/Info/blood_type");
                            Node bloodType = (Node) exp.evaluate(doc, XPathConstants.NODE);

                            System.out.println(
                                    firstName.getTextContent() + ", "
                                    + address.getTextContent() + ", "
                                    + bloodType.getTextContent());

                        } catch (ParserConfigurationException | XPathExpressionException | SAXException ex) {
                            ex.printStackTrace();
                        }

                    } else {

                        record.append(text);

                    }

                }

            }
        } catch (IOException exp) {
            exp.printStackTrace();
        }
    }

}

打印出来的...

john, 200 main street, AB
micheal, 123 baker street, O

总而言之,回到给你这个文件的人那里,打他们一巴掌,然后告诉他们输入有效的 XML 格式......

【讨论】:

  • 感谢您的帮助,对造成的混乱表示歉意。 “”只是我的评论,让帮助我的人知道这是文件中的第一个病人记录。我自己有 xml 架构。对不起,我也遗漏了结束 标记。不过,是的,我需要删除标签“”,只在输出文本文件中显示名称 john,依此类推,其他标签依此类推。我看到这会打印到控制台,但是如何让它写入文本文件?相信我用 xml 标签创建这个文件的人已经被打了哈哈
  • 就像你做任何文件一样,查看Basic I/O了解详情。就我个人而言,我会使用BufferedWriter,但这就是我。
  • 有没有办法在不使用 SAX 和文档生成器的情况下打印某些标签的值?只需编写代码来遍历文本文件并在标签之间提取指定值。当我运行代码时,它不起作用。我不能使用 SAX 解析器来完成这项任务。
  • 简单的答案是,你没有,说真的,这看起来很容易,但却是一项艰巨的任务,是的,我以前尝试过它,但它只是一团糟。问题是,您的示例和实际代码有什么不同?由于我提供的代码适用于示例数据
  • 它抛出一个无效的 XML 错误,说我不能使用 SAX Parser。
【解决方案2】:

使用 DOM 解析器并解析文本文件。您可以在this link 中看到一个示例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-11
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    • 2011-05-10
    • 1970-01-01
    相关资源
    最近更新 更多