在 Pyparsing 中创建手动 ParseResults

发布于 2024-12-31 22:02:11 字数 4099 浏览 1 评论 0原文

交叉发布于http://pyparsing.wikispaces.com/message/view/home/49765026

我正在开发一个解析项目,我需要将一些手动创建的解析结果注入到解析的令牌中。我已将解析操作附加到代码中的适当位置,并且我似乎已成功创建自定义解析结果以添加回更大的语法中。 dump() 和 asxml() 似乎输出正确,但我的代码的其他部分(尝试按名称访问创建的结果)有问题。我可以按列表位置访问,但不能按分配的名称访问。完全有可能我有限的Python知识在某个地方搞乱了我,但由于我无法找到以这种方式创建解析结果的示例,我想我应该从这里开始。这是我的解析结果创建代码。 tripHeaderCustomFields 作为解析操作附加。如果解析特定值(即“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>

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

I am working on a parsing project where I need to inject some manually created parseresults into a parsed token. I have attached a parseaction to the appropriate place in my code, and I seem to have succeeded in creating a custom made parseresult to add back into my larger grammer. dump() and asxml() seem to output correctly, but other parts of my code (trying to access the created results by name) have issues. I can access by list position, but not assigned name. It is entirely possible that my limited python knowledge is messing me up somewhere, but since I have not been able to find an example of creating a parseresults quite this way I thought I would start here. Here is my parseresults creation code. tripHeaderCustomFields is attached as a parseaction. If a particular value is parsed (ie. "TripCode") then some custom parseresults are created and added back in to the final result.

If anyone has tried to create manual parseresults like this, could you please look over my code and tell me if you see any glaring problems? It took hours of trial and error to get this version to work, and I would not be surprised if there is a better or more correct way.

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>

that goes into a bigger result:

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红墙和绿瓦 2025-01-07 22:02:11

我已经重新设计了自定义 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 )

I have reworked my custom ParseResults code, and it now works as expected. I wish I had thought of doing it this way the first time, as it was much easier to figure out. :) I do tend to reinvent the wheel... tripHeaderCustomFields is attached as a ParseAction, and the new ParseResults are added to the parent ParseResults.

This solves the mysterious problem I had with accessing the customField items by name. I am sure it was caused by my not really understanding how the parse results are created behind the scenes, so this works out much better for me.

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 )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文