在Pyparsing中创建手动ParseResults

时间:2012-01-30 01:15:04

标签: pyparsing

http://pyparsing.wikispaces.com/message/view/home/49765026

处转发

我正在开发一个解析项目,我需要将一些手动创建的parseresults注入到解析后的令牌中。我已经将一个parseaction附加到我的代码中的适当位置,我似乎已经成功创建了一个自定义的parseresult,以便添加回我更大的语法中。 dump()和asxml()似乎输出正确,但我的代码的其他部分(尝试按名称访问创建的结果)存在问题。我可以按列表位置访问,但不能分配名称。完全有可能我有限的python知识让我搞砸了,但是由于我无法找到一个创建解析结果的例子,我想我会从这里开始。这是我的parseresults创建代码。 tripHeaderCustomFields作为parseaction附加。如果解析了特定值(即“TripCode”),则创建一些自定义解析结果并将其添加回最终结果。

如果有人试图创建这样的手动解析结果,请你查看我的代码并告诉我你是否看到任何明显的问题?需要花费数小时的试验才能使这个版本正常工作,如果有更好或更正确的方法,我不会感到惊讶。

def addCustomField( self, group, name, datatype, value ):
    """
    custom fields:
    Group: ie, specific airline or category - "USAir, "general"
    Name: name of field, ie "linecheck", "Medical", "Deadhead", "IV Pay"
    DataType: string, int, date, time
    Value: value of field, ie. "checked by joe shmo, #2345", or "1st class medical - bryman"
    """
    #TODO: Need to ask for help, some logic problem somewhere. loosing string name somewhere, but xml prints ok!


    prGroup = ParseResults( group, self.NAME.CFGROUP )
    prName = ParseResults( name, self.NAME.CFNAME )
    prDataType = ParseResults( datatype, self.NAME.CFDATATYPE )
    prValue = ParseResults( value, self.NAME.CFVAULE )

    prList = ParseResults( [] )
    prList += prGroup
    prList += prName
    prList += prDataType
    prList += prValue

    customField = ParseResults( [prList], self.NAME.CUSTOMFIELD )


    return customField


def tripHeaderCustomFields( self, tokens ):
    parseSegment = tokens
    if "TripCode" in parseSegment:
        customField = self.addCustomField( "USAir", "PairingCode", "String", parseSegment["TripCode"] )
        if self.NAME.CUSTOMFIELDS in parseSegment:
            parseSegment[self.NAME.CUSTOMFIELDS] += customField
        else :
            parseSegment += ParseResults( [customField], self.NAME.CUSTOMFIELDS )
    if "Charter" in parseSegment[self.NAME.EFFECTIVEDOWS]:
        customField = self.addCustomField( "USAir", "Charter", "Boolean", "True" )
        if self.NAME.CUSTOMFIELDS in parseSegment:
            parseSegment[self.NAME.CUSTOMFIELDS] += customField
        else :
            parseSegment += ParseResults( [customField], self.NAME.CUSTOMFIELDS )
    return tokens

returns a seemingly correct token, 

     <CustomFields>
         <CustomField>
            <Group>USAir</Group>
            <Name>EquipmentChange</Name>
            <DataType>Boolean</DataType>
           <Value>True</Value>
         </CustomField>
         <CustomField>
            <Group>USAir</Group>
            <Name>EquipmentChange</Name>
            <DataType>Boolean</DataType>
            <Value>True</Value>
          </CustomField>
      </CustomFields>

会产生更大的结果:

<Trip>
    <TripNumber>8510</TripNumber>
    <EffectiveDOWs>
      <EXCPT>EXCPT</EXCPT>
      <DayOfWeek>MO</DayOfWeek>
      <DayOfWeek>TH</DayOfWeek>
      <DayOfWeek>FR</DayOfWeek>
    </EffectiveDOWs>
    <ReportTime>
      <Hours>21</Hours>
      <Minutes>40</Minutes>
    </ReportTime>
    <TripCode>N</TripCode>
    <EffectiveDateStart>
      <Month>APR</Month>
      <Day>02</Day>
    </EffectiveDateStart>
    <EffectiveDateEnd>
      <Month>APR</Month>
      <Day>27</Day>
    </EffectiveDateEnd>
    <CustomFields>
      <CustomField>
        <Group>USAir</Group>
        <Name>PairingCode</Name>
        <DataType>String</DataType>
        <Value>N</Value>
      </CustomField>
    </CustomFields>
    <RequiredCrew>
      <Captain>1</Captain>
      <FO>1</FO>
    </RequiredCrew>

    .....snip....

</Trip>

1 个答案:

答案 0 :(得分:1)

我已经重新设计了我的自定义ParseResults代码,它现在可以按预期工作了。我希望我第一次想到这样做,因为它更容易弄明白。 :)我确实倾向于重新发明轮子... tripHeaderCustomFields作为ParseAction附加,新的ParseResults被添加到父ParseResults。

这解决了我通过名称访问customField项目时遇到的神秘问题。我确信这是由于我不太了解如何在幕后创建解析结果,所以这对我来说效果更好。

def tripHeaderCustomFields( self, tokens ):
    parseSegment = tokens
    if "TripCode" in parseSegment:
        customField = self.addCustomField( "USAir", "PairingCode", "String", parseSegment["TripCode"], parseSegment )
    if "Charter" in parseSegment[self.NAME.EFFECTIVEDOWS]:
        customField = self.addCustomField( "USAir", "Charter", "Boolean", "True", parseSegment )

def buildCustomFieldString( self, group, name, datatype, value ):
    #TODO: replace any stray "|" that might be in input strings

    text = group + "|" + name + "|" + datatype + "|" + value
    return text

def addCustomField( self, group, name, datatype, value, token ):
    """
    custom fields:
    Group: ie, specific airline or category - "USAir, "general"
    Name: name of field, ie "linecheck", "Medical", "Deadhead", "IV Pay"
    DataType: string, int, date, time
    Value: value of field, ie. "checked by joe shmo, #2345", or "1st class medical - bryman"
       <CustomFields>
          <CustomField>
            <Group>USAir</Group>
            <Name>EquipmentChange</Name>
            <DataType>Boolean</DataType>
            <Value>True</Value>
          </CustomField>
          <CustomField>
            <Group>USAir</Group>
            <Name>EquipmentChange</Name>
            <DataType>Boolean</DataType>
            <Value>True</Value>
          </CustomField>
        </CustomFields>
    """
    pGroup = Word( alphanums )( self.NAME.CFGROUP )
    pName = Word( alphanums )( self.NAME.CFNAME )
    pDatatype = Word( alphanums )( self.NAME.CFDATATYPE )
    pValue = Word( alphanums )( self.NAME.CFVAULE )
    delim = Suppress( "|" )
    customField = Group( pGroup + delim + pName + delim + pDatatype + delim + pValue )( self.NAME.CUSTOMFIELD )
    text = self.buildCustomFieldString( group, name, datatype, value )
    if self.NAME.CUSTOMFIELDS in token:
        token[self.NAME.CUSTOMFIELDS] += customField.parseString( text )
    else :
        token += Group( customField )( self.NAME.CUSTOMFIELDS ).parseString( text )