stax xml 与 getname 函数混淆

stax xml confusion with getname function

我有一个这样的 xml 文件:

<comment type="PTM">
    <text evidence="19">Sumoylated following its interaction with PIAS1 and UBE2I.</text>
</comment>
<comment type="PTM">
    <text evidence="17">Ubiquitinated, leading to proteasomal degradation.</text>
</comment>
<comment type="disease">
    <text>A chromosomal aberration involving ZMYND11 is a cause of acute poorly differentiated myeloid leukemia. Translocation (10;17)(p15;q21) with MBTD1.</text>
</comment>
<comment type="disease" evidence="23">
    <disease id="DI-04257">
        <name>Mental retardation, autosomal dominant 30</name>
        <acronym>MRD30</acronym>
        <description>A disorder characterized by significantly below average general intellectual functioning associated with impairments in adaptive behavior and manifested during the developmental period. MRD30 patients manifest mild intellectual disability and subtle facial dysmorphisms, including hypertelorism, ptosis, and a wide mouth.</description>
        <dbReference type="MIM" id="616083"/>
    </disease>
    <text>The disease is caused by mutations affecting the gene represented in this entry.</text>
</comment>
<comment type="similarity">
    <text evidence="8">Contains 1 bromo domain.</text>
</comment>
<comment type="similarity">
    <text evidence="9">Contains 1 MYND-type zinc finger.</text>
</comment>

我用stax提取疾病信息。这是我的代码的一部分:

XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader eventReader = factory.createXMLEventReader( new FileReader(p)); 

            while(eventReader.hasNext()){
               XMLEvent event = eventReader.nextEvent();
               switch(event.getEventType()){
                  case XMLStreamConstants.START_ELEMENT:
                     StartElement startElement = event.asStartElement();
                     String qName = startElement.getName().getLocalPart();
                     if (qName.equalsIgnoreCase("comment")) {
                        System.out.println("Start Element : comment");
                        Iterator<Attribute> attributes = startElement.getAttributes();
                        Attribute a = attributes.next(); 
                         System.out.println("ATRIBUTES " + a.getName());
                        type = a.getValue();
                        System.out.println("Roll No : " + type);
                     }  else if(qName.equalsIgnoreCase("text") && type.equals("disease")){ text = true; } 

                     break;

                    case XMLStreamConstants.CHARACTERS:
                     Characters characters = event.asCharacters();
                     if(text){ res = res + " " + characters.getData(); 
                        //System.out.println("TEXT: " + res);
                        text = false;
                     }
                    break;

                  case  XMLStreamConstants.END_ELEMENT:
                     EndElement endElement = event.asEndElement();
                     if(endElement.getName().getLocalPart().equalsIgnoreCase("comment")){
                        //System.out.println("End Element : comment"); 
                        //System.out.println();
                     }
                     break; 

对于这种类型的线路:

<comment type="disease">

我可以正确提取信息,但是当我尝试在这一行中查找评论类型 "disease" 时:

<comment type="disease" evidence="23">

它给了我 type=evidence 而不是 type=disease 它应该是。因此它不会从这种行中保存任何内容。

抱歉,没有直接的答案,但评论了如何有效地使用 StaX 或 XmlPull:流式 XML 解析器旨在友好地进行递归下降解析(避免显式状态建模,这是您经常需要的东西SAX 解析器)——在您的情况下,我希望使用以下方法(拒绝或忽略所有意外内容):

Comment parseComment(XMLEventReader eventReader) {
   // call parseText and parseDisease for the corresponding element starts
}

Text parseText(XMLEventReader eventReader) {
}

Disease parseDisease(XmlEventReader eventReader) {
} 

也就是说,需要权衡取舍:如果您不需要流式传输方面(性能),最好只解析为 DOM,然后根据需要通过遍历提取信息或窥视 DOM,完全避免低水平 XML API。

首先我们能否养成使用有用变量名的习惯,你有以下变量及其类型:a(node), text(boolean), qName(String)... 这些变量让我摸不着头脑,想知道它们是什么:

a - 只是不是一个有用的名称,它实际上应该是 typeAttr 之类的东西,或者注意它应该是 type="" 属性

text - 它是一个布尔值?!也许 collectText 会更合适,因为它指定您应该收集下一个文本事件值。

qName - 它是一个字符串,它是 QName 的 localPart,如果它不是 QName,则不要将其命名为一个..


但是你已经明白了。您的问题在于获取属性的位置。在 XML 中,属性没有特定的顺序,不会也不应该按照它们定义的顺序 return。在您的代码中,您有以下内容

Iterator<Attribute> attributes = startElement.getAttributes();
Attribute a = attributes.next(); 
System.out.println("ATRIBUTES " + a.getName());
type = a.getValue();

这里您从元素中获取第一个属性并将类型设置为等于它的值。正如我提到的,XML 属性没有特定顺序,因此您将获得 evidence 属性。您应该按名称获取属性:

Attribute a = startElement.getAttributeByName(QName.valueOf("type"));
System.out.println("ATRIBUTES " + a.getName());
type = a.getValue();

通过使用 Stax,我假设您正在处理大型文档或资源有限的平台...事实是内存开销主要是一个 DOM 相关问题。另一方面,VTD-XML 比 DOM 高效得多,同时几乎保留了 DOM 编码风格的所有优点...请阅读这篇最新的研究论文以获取更多信息

http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf

import com.ximpleware.*;
public class queryAttr {
    public static void main(String[] s) throws VTDException{
        VTDGen vg = new VTDGen();
        vg.selectLcDepth(5);// improve XPath performance for deep document
        if (!vg.parseFile("input.xml", false))
            return;
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn);
        ap.selectXPath("/root/comment[@type='disease' and @evidence='23']");
        int i=0,j=0;
        while((i=ap.evalXPath())!=-1){
            if (vn.toElement(VTDNav.FIRST_CHILD)){
                System.out.println(" element name: "+ vn.toString(vn.getCurrentIndex()));
                j=vn.getText();
                if (i!=-1)
                    System.out.println(""+vn.toString(i));
                if (vn.toElement(VTDNav.NS)){
                    System.out.println(" element name: "+ vn.toString(vn.getCurrentIndex()));
                    j=vn.getText();
                    if (i!=-1)
                        System.out.println("text node==>"+vn.toString(i));
                }
                if (vn.toElement(VTDNav.NS)){
                    System.out.println(" element name: "+ vn.toString(vn.getCurrentIndex()));
                    j=vn.getText();
                    if (i!=-1)
                        System.out.println("text node==>"+vn.toString(i));
                }
                if (vn.toElement(VTDNav.NS)){
                    System.out.println(" element name: "+ vn.toString(vn.getCurrentIndex()));
                    j=vn.getText();
                    if (i!=-1)
                        System.out.println("text node==>"+vn.toString(i));
                }
                vn.toElement(VTDNav.PARENT);
            }

        }
    }
}