[英]XML parse section by section in SAX or StAX
我的XML文件的簡短版本如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<MzIdentML id="MS-GF+">
<SequenceCollection xmlns="http://psidev.info/psi/pi/mzIdentML/1.1">
<DBSequence length="146" id="DBSeq143">
<cvParam cvRef="PSI-MS" accession="MS:1001088"></cvParam>
</DBSequence>
<Peptide id="Pep7">
<PeptideSequence>MFLSFPTTK</PeptideSequence>
<Modification location="1" monoisotopicMassDelta="15.994915">
<cvParam cvRef="UNIMOD" accession="UNIMOD:35" name="Oxidation"></cvParam>
</Modification>
</Peptide>
<PeptideEvidence dBSequence_ref="DBSeq143" id="PepEv_160_1_18"></PeptideEvidence>
<PeptideEvidence dBSequence_ref="DBSeq143" id="PepEv_275_8_133"></PeptideEvidence>
</SequenceCollection>
</MzIdentML>
我想分別獲取DBSequence,Peptide和PeptideEvidence詳細信息,但是要獲取父級和子級的屬性(或嵌套的子級..如果有),換句話說,我希望在以下各節中將所有屬性作為鍵值對:
----------------------------------------------------------------------
<DBSequence length="146" id="DBSeq143">
<cvParam cvRef="PSI-MS" accession="MS:1001088"></cvParam>
</DBSequence>
----------------------------------------------------------------------
<Peptide id="Pep7">
<PeptideSequence>MFLSFPTTK</PeptideSequence>
<Modification location="1" monoisotopicMassDelta="15.994915">
<cvParam cvRef="UNIMOD" accession="UNIMOD:35" name="Oxidation"></cvParam>
</Modification>
</Peptide>
----------------------------------------------------------------------
<PeptideEvidence dBSequence_ref="DBSeq143" id="PepEv_160_1_18"></PeptideEvidence>
<PeptideEvidence dBSequence_ref="DBSeq143" id="PepEv_275_8_133"></PeptideEvidence>
----------------------------------------------------------------------
例如,如果我們考慮<DBSequence>
部分:
<DBSequence length="146" id="DBSeq143">
<cvParam cvRef="PSI-MS" accession="MS:1001088"></cvParam>
</DBSequence>
應該輸出為:
DBSequence=>length=146;id=DBSeq143;cvRef=PSI-MS;accession=MS:1001088;
這是我在SAX中編寫的代碼:
package lucene.parse;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MzIdentMLSAXParser extends DefaultHandler {
private boolean isDBsequence = false;
String DBSequenceSection;
String PeptideEvidenceDocument;
public static void main(String[] argv) throws SAXException, ParserConfigurationException, IOException {
MzIdentMLSAXParser ps = new MzIdentMLSAXParser("file_path_here/sample.xml");
}
public MzIdentMLSAXParser(String dataDir) throws FileNotFoundException, SAXException, ParserConfigurationException, IOException {
FileInputStream fis = new FileInputStream(dataDir);
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.parse(fis, this);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (qName.equals("DBSequence")) {
// each time we found a new DBSequence, we re-initialize DBSequenceSection
DBSequenceSection = "";
// get attributes of DBSequence
for (int i = 0; i < atts.getLength(); i++) {
DBSequenceSection += atts.getQName(i) + "=" + atts.getValue(i) + ";";
}
isDBsequence = true;
} else if ((qName.equals("cvParam")) && (isDBsequence)) {
// get attributes of cvParam which are belongs to DBSequence
// there can be cvParam that are not belongs to DBSequence.
for (int i = 0; i < atts.getLength(); i++) {
DBSequenceSection += atts.getQName(i) + "=" + atts.getValue(i) + ";";
}
} else if (qName.equals("PeptideEvidence")) {
// each time we found a new PeptideEvidence, we re-initialize docuDBSequenceSectionment
PeptideEvidenceDocument = "";
for (int i = 0; i < atts.getLength(); i++) {
PeptideEvidenceDocument += atts.getQName(i) + "=" + atts.getValue(i) + ";";
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("DBSequence")) {
System.out.println(qName +"=>"+DBSequenceSection);
isDBsequence = false;
} else if (qName.equals("PeptideEvidence")) {
System.out.println(qName +"=>"+PeptideEvidenceDocument);
}
}
}
有沒有簡單的方法可以做到這一點? 因為我有很多這樣的帶有嵌套節點的標簽。 這里的挑戰是<cvParam>
不僅出現在<DBSequence>
標記中,而且出現在其他標記(例如<Modification>
等)中。我也嘗試使用StAX。 但是做不到。
這是使用StAX的工作示例。 StAX在解析已知的XML結構時表現出色,但是也可以用於動態解析。
此代碼依賴於知識,例如,知道我們想要的內容DBSequence
, Peptide
和PeptideEvidence
,而且PeptideSequence
具有文本內容,而有的則沒有。
這些方法使用遞歸來遵循XML的結構。
public static void main(String[] args) throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<MzIdentML id=\"MS-GF+\">\n" +
" <SequenceCollection xmlns=\"http://psidev.info/psi/pi/mzIdentML/1.1\">\n" +
" <DBSequence length=\"146\" id=\"DBSeq143\">\n" +
" <cvParam cvRef=\"PSI-MS\" accession=\"MS:1001088\"></cvParam>\n" +
" </DBSequence>\n" +
" <Peptide id=\"Pep7\">\n" +
" <PeptideSequence>MFLSFPTTK</PeptideSequence>\n" +
" <Modification location=\"1\" monoisotopicMassDelta=\"15.994915\">\n" +
" <cvParam cvRef=\"UNIMOD\" accession=\"UNIMOD:35\" name=\"Oxidation\"></cvParam>\n" +
" </Modification>\n" +
" </Peptide>\n" +
" <PeptideEvidence dBSequence_ref=\"DBSeq143\" id=\"PepEv_160_1_18\"></PeptideEvidence>\n" +
" <PeptideEvidence dBSequence_ref=\"DBSeq143\" id=\"PepEv_275_8_133\"></PeptideEvidence>\n" +
" </SequenceCollection>\n" +
"</MzIdentML>";
XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(new StringReader(xml));
try {
reader.nextTag();
search(reader);
} finally {
reader.close();
}
}
private static void search(XMLStreamReader reader) throws XMLStreamException {
// reader must be on START_ELEMENT upon entry, and will be on matching END_ELEMENT on return
assert reader.getEventType() == XMLStreamConstants.START_ELEMENT;
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
String name = reader.getLocalName();
switch (name) {
case "DBSequence":
case "Peptide":
case "PeptideEvidence": {
Map<String, String> props = new LinkedHashMap<>();
collectProps(reader, props);
System.out.println(name + ": " + props);
break; }
default:
search(reader);
}
}
}
private static void collectProps(XMLStreamReader reader, Map<String, String> props) throws XMLStreamException {
// reader must be on START_ELEMENT upon entry, and will be on matching END_ELEMENT on return
assert reader.getEventType() == XMLStreamConstants.START_ELEMENT;
for (int i = 0; i < reader.getAttributeCount(); i++)
props.put(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
String name = reader.getLocalName();
switch (name) {
case "PeptideSequence":
props.put(name, reader.getElementText());
break;
default:
while (reader.nextTag() == XMLStreamConstants.START_ELEMENT)
collectProps(reader, props);
}
}
輸出值
DBSequence: {length=146, id=DBSeq143, cvRef=PSI-MS, accession=MS:1001088}
Peptide: {id=Pep7, PeptideSequence=MFLSFPTTK, location=1, monoisotopicMassDelta=15.994915, cvRef=UNIMOD, accession=UNIMOD:35, name=Oxidation}
PeptideEvidence: {dBSequence_ref=DBSeq143, id=PepEv_160_1_18}
PeptideEvidence: {dBSequence_ref=DBSeq143, id=PepEv_275_8_133}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.