1

QXmlStreamReader を使用して XML ドキュメントを読み込もうとしています。リーダーへのポインターを他のクラスに渡そうとすると、問題が発生します。1 つのクラスでリーダーのインスタンスを作成します。そのクラスは、新しいクラスを定義するブロックになるまで XML を読み取ります。新しいクラスのインスタンスを作成し、そのクラスで関数を呼び出して、そのクラスに固有の XML を引き続き読み取ります。例えば:

void SF_UnitClass::ReadModes()
{
    Q_ASSERT(XML.isStartElement() && XML.name() == MODES);
    NumModes = XML.attributes().value(COUNT).toInt();            
    while (XML.readNextStartElement())                                          
    {
        if (XML.name() == MODE)                                            
        {                                                                      
            ModeClass* pMode = new ModeClass(this);                          
            ModeList += XML.attributes().value(ID).toString();                
            pMode->ReadXML(&XML);                                              
            {                                                                  
            }
        }
        else                                                                    
        {
            XML.raiseError(QObject::tr("Something other than Mode block encountered in Modes block"));
        }
    }
}

void ModeClass::ReadXML(QXmlStreamReader* pXML)                                 
{                                                                               
    Q_ASSERT(pXML->isStartElement() && pXML->name() == MODE);                   
    while (pXML->readNextStartElement())                                        
    {                                                                           
        int nameIndex = ModeList.indexOf(pXML->name().toString());            
        if(nameIndex != -1)                                                     
        {                                                                       
            switch(nameIndex)                                                   
            {                                                                   
                case 0:                                                         
                {                                                               
    qDebug() << "Mode: Receivers";                                              
                    NumReceivers = pXML->readElementText().toInt();             
                    break;                                                      
                }                                                               
                case 1:                                                         
                {                                                               
    qDebug() << "Mode: Channels";                                               
                    ReadChannels(pXML);                                         
                    break;                                                      
                }                                                               
                case 2:                                                         
                {                                                               
    qDebug() << "Mode: Servos";                                                 
                    ReadServos(pXML);                                           
                    break;                                                      
                }                                                               
            }                                                                   
        }                                                                       
        else                                                                    
        {                                                                       
    qDebug() << "Mode: Error " << name;                                         
            pXML->raiseError(QObject::tr("Unrecognized keyword for Mode"));     
        }                                                                       
    }                                                                           
}                                                                               

void ModeClass::ReadChannels(QXmlStreamReader* pXML)                            
{                                                                               
    Q_ASSERT(pXML->isStartElement() && pXML->name() == CHANNELS);               
    NumChannels = pXML->attributes().value(COUNT).toInt();                      
    while (pXML->readNextStartElement())                                        
    {                                                                           
        if (pXML->name() == CHANNEL)                                            
        {                                                                       
    qDebug() << "Mode: Read Channel";                                           
            ChannelClass* pChannel = new ChannelClass(this);                    
            pChannel->ReadXML(pXML);                                            
        }                                                                       
        else                                                                    
        {                                                                       
            pXML->raiseError(QObject::tr("Something other than Channel block enc
        }                                                                       
    }                                                                           
}                                                                               

void ModeClass::ReadServos(QXmlStreamReader* pXML)                              
{                                                                               
    Q_ASSERT(pXML->isStartElement() && pXML->name() == SERVOS);                 
    NumServos = pXML->attributes().value(COUNT).toInt();                        
    while (pXML->readNextStartElement())                                        
    {                                                                           
        if (pXML->name() == SERVO)                                              
        {                                                                       
    qDebug() << "Mode: Read Servo";                                             
            ServoClass* pServo = new ServoClass(this);                          
            pServo->ReadXML(pXML);                                              
        }                                                                       
        else                                                                    
        {                                                                       
    qDebug() << "Servos: raiseError";                                           
            pXML->raiseError(QObject::tr("Something other than Servo block encou
        }                                                                       
    }                                                                           
    qDebug() << "Mode: Read Servos Exit";                                       
}                                                                               

void ChannelClass::ReadXML(QXmlStreamReader* pXML)                              
{                                                                               
    Q_ASSERT(pXML->isStartElement() && pXML->name() == CHANNEL);                
    ChannelNumber = pXML->attributes().value(ID).toInt();                       
    while (pXML->readNextStartElement())                                        
    {                                                                           
        int nameIndex = ChannelList.indexOf(pXML->name().toString());           
        if(nameIndex != -1)                                                     
        {                                                                       
            switch(nameIndex)                                                   
            {                                                                   
                case 0:                                                         
                {                                                               
                    UserName = pXML->readElementText();                         
                    break;                                                      
                }                                                               
                case 1:                                                         
                {                                                               
                    EndPointHold = String2Bool(pXML->readElementText());        
                    break;                                                      
                }                                                               
                case 2:                                                         
                {                                                               
                    ServoPriority = String2Bool(pXML->readElementText());       
                    break;                                                      
                }                                                               
            }                                                                   
        }                                                                       
        else                                                                    
        {                                                                       
            pXML->raiseError(QObject::tr("Unrecognized keyword for Channel"));  
        }                                                                       
    }                                                                           
}                                                                               

void ServoClass::ReadXML(QXmlStreamReader* pXML)                                
{                                                                               
    Q_ASSERT(pXML->isStartElement() && pXML->name() == SERVO);                  
    ServoNumber = pXML->attributes().value(ID).toInt();                         
    while (pXML->readNextStartElement())                                        
    {                                                                           
        int nameIndex = ServoList.indexOf(pXML->name().toString());             
    qDebug() << "Servo: NameIndex: " << nameIndex;                              

        if(nameIndex != -1)                                                     
        {                                                                       
            switch(nameIndex)                                                   
            {                                                                   
                case 0:                                                         
                {                                                               
                    Offset = pXML->readElementText().toInt();                   
                    break;                                                      
                }                                                               
                case 1:                                                         
                {                                                               
                    PosFactor = pXML->readElementText().toInt();                
                    break;                                                      
                }                                                               
                case 2:                                                         
                {                                                               
                    NegFactor = pXML->readElementText().toInt();                
                    break;                                                      
                }                                                               
                case 3:                                                         
                {                                                               
                    SecServo = pXML->readElementText().toInt();                 
                    break;                                                      
                }                                                               
                case 4:                                                         
                {                                                               
                    Unit = pXML->readElementText().toInt();                     
                    break;                                                      
                }                                                               
                case 5:                                                         
                {                                                               
                    Ser1 = pXML->readElementText().toInt();                     
                    break;                                                      
                }                                                               
                case 6:                                                         
                {                                                               
                    Ser2 = pXML->readElementText().toInt();                     
                    break;                                                      
                }                                                               
                case 7:                                                         
                {                                                               
                    Ser3 = pXML->readElementText().toInt();                     
                    break;                                                      
                }                                                               
            }                                                                   
        }                                                                       
        else                                                                    
        {                                                                       
    qDebug() << "Servo: raiseError";                                            
            pXML->raiseError(QObject::tr("Unrecognized keyword for Servo block")
        }                                                                       
    }                                                                           
    qDebug() << "Servo: Exit ";                                                 
}                                                                               

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<SmartFlyUnit version="1.0">
    <UnitName>PowerExpander Eq10E</UnitName>
    <UnitCode>PE-5</UnitCode>
    <UnitID>1</UnitID>
    <MinRev>1.0</MinRev>
    <MaxRev>1.9</MaxRev>
    <Servos>36</Servos>
    <Outputs>32</Outputs>
    <UnitMode>Chan</UnitMode>
    <Modes Count="2">
        <Mode ID="Chan">
            <Receivers>1</Receivers>
            <Channels Count="10">
                <Channel ID="0">
                    <UserName></UserName>
                    <EndPtHold>Off</EndPtHold>
                    <ServoPri>Off</ServoPri>
                </Channel>
                <Channel ID="1">
                    <UserName></UserName>
                    <EndPtHold>Off</EndPtHold>
                    <ServoPri>Off</ServoPri>
                </Channel>
            </Channels>
            <Servos Count="36">
                <Servo ID="0">
                    <Offset>0</Offset>
                    <PosFact>1.0000</PosFact>
                    <NegFact>1.0000</NegFact>
                    <Reverse>Off</Reverse>
                    <SecServo>0xFF</SecServo>
                    <Unit>0xFF</Unit>
                    <Ser1>0xFF</Ser1>
                    <Ser2>0xFF</Ser2>
                    <Ser3>0xFF</Ser3>
                </Servo>
                <Servo ID="1">
                    <Offset>0</Offset>
                    <PosFact>1.0000</PosFact>
                    <NegFact>1.0000</NegFact>
                    <Reverse>Off</Reverse>
                    <SecServo>0xFF</SecServo>
                    <Unit>0xFF</Unit>
                    <Ser1>0xFF</Ser1>
                    <Ser2>0xFF</Ser2>
                    <Ser3>0xFF</Ser3>
                </Servo>
            </Servos>
        </Mode>
    </Modes>
    <MCUs Count="1">
        <MCU ID="0">
            <FileName>/PE-5/PE-5_M0_1_00.sffw</FileName>
        </MCU>
    </MCUs>
    <FPGAs Count="1">
        <FPGA ID="0">
            <Configs Count="2">
                <Config ID="0">
                    <FileName>/PE-5/PE-5_F0C0_1_00.sffw</FileName>
                </Config>
                <Config ID="1">
                    <FileName>/PE-5/PE-5_F0C1_1_00.sffw</FileName>
                </Config>
            </Configs>
        </FPGA>
    </FPGAs>
</SmartFlyUnit>

ModeClass がチャネルとサーボ ブロックを認識するために使用するコードを追加しました。ChannelClass と ServoClass からのコードも追加しました。最後に、XML ファイルの編集バージョンを追加しましたが、問題を示すには十分でした。この XML は、私の TreeWidget コード (表示されていません) に適切に読み込まれます。上記のコードを読み込むと、すべてのチャネルが正しく読み込まれ、最初のサーボ ブロックが読み込まれ、ModeClass::ReadServos の次のサーボを読み込む代わりに、メインの ModeClass ループまで戻ります。これが大量のコードであることは知っていますが、問題を示す唯一の方法のように思われました。ありがとう、

4

1 に答える 1

0

Qtのドキュメントは次のように述べています:

現在の要素内の次の開始要素まで読み取ります。開始要素に到達したときに true を返します。終了要素に達した場合、またはエラーが発生した場合は false が返されます。

したがって、開始要素に遭遇すると、使用readNextStartElement()すると、見つかった要素内が検索されます

すなわち

<xml>
</xml>
<xml>
</xml>

ここで何が起こるか:

  1. readNextStartElement()<xml>最初のノードで停止します
  2. readNextStartElement()検出されると false を返します</xml>

少し変更された例では:

<xml>
  <child>
  </child>
</xml>
<xml>
</xml>
  1. readNextStartElement()<xml>最初のノードで停止します
  2. readNextStartElement()<child>ノードで停止します
  3. readNextStartElement()ノード内にxmlノードがないため、falseを返し<child>ます

あなたは何をすべきですか、あなたは尋ねますか?

興味のあるノードに到達し、必要なすべての情報を読み取った後、呼び出す必要があるskipCurrentElement()ためQXmlStreamReader、現在の要素の最後に移動します

したがって、最初のサンプルを少し変更します。

<xml>
</xml>
<xml>
</xml>
  1. readNextStartElement()<xml>最初のノードで停止します
  2. skipCurrentElement()<xml>最初のノードを閉じると停止します
  3. readNextStartElement()<xml>2番目のノードで停止します
于 2014-07-17T07:29:03.877 に答える