Search code examples
iphonexmlkissxml

kissXML returning no values for xpath query


Im trying to parse the following XML file(generated on iphone with KISSxml) with KissXML :

<?xml version="1.0" encoding="UTF-8"?>
<SnowProfile xmlns="http://caaml.org/Schemas/V5.0/Profiles/SnowProfileIACS" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://caaml.org/Schemas/V5.0/Profiles/SnowProfileIACS http://caaml.org/Schemas/V5.0/Profiles/SnowprofileIACS/CAAMLv5_SnowProfileIACS.xsd" gml:id="2011-09-04-Home">
  <metaDataProperty>
    <MetaData>
      <dateTimeReport>2011-09-04T18:45:10-0700</dateTimeReport>
      <srcRef>
        <Operation>
          <name>My op</name>
          <contactPerson>
            <Person>
              <name>Jesse</name>
            </Person>
          </contactPerson>
        </Operation>
      </srcRef>
    </MetaData>
  </metaDataProperty>
  <validTime>
    <TimeInstant>
      <timePosition>2011-09-04T18:45:10-0700</timePosition>
    </TimeInstant>
  </validTime>
  <snowProfileResultsOf>
    <SnowProfileMeasurements dir="top down">
      <comment>Testing</comment>
      <profileDepth uom="cm">58</profileDepth>
      <skyCond>BKN</skyCond>
      <precipTI>None</precipTI>
      <airTempPres uom="degC">2</airTempPres>
      <windSpd uom="ms-1">5</windSpd>
      <windDir>
        <AspectPosition>
          <position>E</position>
        </AspectPosition>
      </windDir>
      <hS>
        <Components>
          <snowHeight uom="cm">3</snowHeight>
        </Components>
      </hS>
      <penetrationSki uom="cm">14</penetrationSki>
      <penetrationFoot uom="cm">8</penetrationFoot>
      <penetrationRam uom="cm">22</penetrationRam>
      <stratProfile>
        <Layer>
          <depthTop uom="cm">0</depthTop>
          <thickness uom="cm">27</thickness>
          <grainFormPrimary>PPsd</grainFormPrimary>
          <grainSize uom="mm">14</grainSize>
          <hardness uom="">4F</hardness>
          <lwc uom="">W</lwc>
          <density uom="kg/m3">310</density>
          <validFormationTime>
            <timeInstant>
              <timePosition>2011-09-05</timePosition>
            </timeInstant>
          </validFormationTime>
        </Layer>
        <Layer>
          <depthTop uom="cm">27</depthTop>
          <thickness uom="cm">31</thickness>
          <grainFormPrimary>PPnd</grainFormPrimary>
          <grainFormSecondary>PPpl</grainFormSecondary>
          <grainSize uom="mm">11</grainSize>
          <hardness uom="">1F</hardness>
          <lwc uom="">S</lwc>
          <density uom="kg/m3">263</density>
          <validFormationTime>
            <timeInstant>
              <timePosition>2011-07-05</timePosition>
            </timeInstant>
          </validFormationTime>
        </Layer>
      </stratProfile>
      <tempProfile uomDepth="cm" uomTemp="C">
        <Obs>
          <depth>2</depth>
          <snowTemp>0</snowTemp>
        </Obs>
        <Obs>
          <depth>18</depth>
          <snowTemp>-4</snowTemp>
        </Obs>
        <Obs>
          <depth>52</depth>
          <snowTemp>-1</snowTemp>
        </Obs>
      </tempProfile>
      <stbTests>
        <RBlockTest>
          <comment>Test</comment>
          <failedOn>
            <Layer uom="cm">
              <depthTop>25</depthTop>
            </Layer>
            <Results>
              <testScore>3</testScore>
              <fractureCharacter>Q3</fractureCharacter>
            </Results>
          </failedOn>
        </RBlockTest>
      </stbTests>
    </SnowProfileMeasurements>
  </snowProfileResultsOf>
  <locRef>
    <ObsPoint>
      <name>Home</name>
      <validElevation>
        <ElevationPosition uom="m">
          <position>110</position>
        </ElevationPosition>
      </validElevation>
      <validAspect>
        <AspectPosition>
          <position>SW</position>
        </AspectPosition>
      </validAspect>
      <validSlopeAngle>
        <SlopeAnglePosition uom="deg">
          <position>2</position>
        </SlopeAnglePosition>
      </validSlopeAngle>
      <pointLocation>
        <gml:Point srsDimension="2">
          <gml:pos></gml:pos>
        </gml:Point>
      </pointLocation>
    </ObsPoint>
  </locRef>
</SnowProfile>

Using the following code to create a core data object from it:

-(BOOL)importFile:(NSString *)fileName error:(NSError **)error{
    NSData *data = [[NSData alloc] initWithContentsOfFile:fileName];
    if(data == nil)
        return NO;
    DDXMLDocument *doc = [[DDXMLDocument alloc] initWithData:data options:0 error:error];
    //if(error != nil)
    if(doc == nil)
        return NO;

    snowPit *pit = [snowPit pitForCAAMLProfile:doc];
    if(pit != nil)
        return YES;
    else
        return NO;
}

+(snowPit *)pitForCAAMLProfile:(DDXMLDocument *)xmlDoc{
    NSLog(@"%@", [xmlDoc XMLStringWithOptions:DDXMLNodePrettyPrint] );

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
    NSError *err;

    snowPit *newPit = [[pitManager sharedManager] newPitWithoutDefaults];
    NSArray *fields = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"CAAMLImportFields" ofType:@"plist"]];
    for(NSDictionary *importField in fields){
        NSString *field = [importField valueForKey:@"field"];
        NSString *xpath = [importField valueForKey:@"xpath"];
        NSString *attribute = [importField valueForKey:@"attribute"];
        NSArray *nodes;
        if(xpath != nil && [xpath length] > 0){
            nodes = [xmlDoc nodesForXPath:xpath error:nil];
            NSLog(@"Field:%@, xpath:%@, attribute:%@ nodes:%i", field, xpath, attribute, [nodes count]);
            if(nodes != nil && [nodes count] > 0){
                NSString *value;
                if(attribute != nil && [attribute length] > 0){
                    DDXMLNode *attNode = [[nodes objectAtIndex:0] attributeForName:attribute];
                    if(attNode != nil)
                        value = [attNode stringValue];
                }else
                    value = [[nodes objectAtIndex:0] stringValue];
                if(value != nil && [value length] > 0)
                    [newPit setValue:value forKey:field];
            }
        }
    }
    [dateFormatter release];
    return newPit;
}

But so far every XPath query I try returns an array of 0 length.

To get the value for name i have tried //Person/name Person/name //name name And they all return a 0 length array. Even a query for /SnowProfile returns a 0 length array which leads me to think that something is going wrong with the xml parsing. I have validated the XML file and it is fine, and from the NSlog output I can tell that the file is being loaded.


Solution

  • There is a namespace defined xmlns:gml="http://www.opengis.net/gml"

    From my recollection of xpath, you need to specify that when you do an xpath query. Try /gml:SnowProfile to see if that returns something other than a 0 length array. You will then know if this will solve your problem.