KissXML 不返回 xpath 查询的值

Posted

技术标签:

【中文标题】KissXML 不返回 xpath 查询的值【英文标题】:kissXML returning no values for xpath query 【发布时间】:2011-09-06 15:23:18 【问题描述】:

我正在尝试使用 KissXML 解析以下 XML 文件(在 iphone 上使用 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>

使用以下代码从中创建一个核心数据对象:

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

但到目前为止,我尝试的每个 XPath 查询都返回一个长度为 0 的数组。

为了获得名称的值,我尝试了//Person/namePerson/name//namename,它们都返回一个长度为 0 的数组。即使是对/SnowProfile 的查询也会返回一个长度为0 的数组,这让我认为xml 解析出了点问题。我已经验证了 XML 文件,它很好,从 NSlog 输出中我可以看出文件正在加载。

【问题讨论】:

【参考方案1】:

定义了一个命名空间xmlns:gml="http://www.opengis.net/gml"

根据我对 xpath 的回忆,您需要在执行 xpath 查询时指定这一点。试试/gml:SnowProfile 看看它是否返回一个长度为 0 的数组以外的东西。然后你就会知道这是否能解决你的问题。

【讨论】:

错误原来是默认命名空间 xmlns="caaml.org/Schemas/V5.0/Profiles/SnowProfileIACS",为了使其正确解析,我必须将文件加载为 mutableString 并在制作之前摆脱命名空间声明将其转换为 DDXmlDocument。【参考方案2】:

您必须将 html 标记的“xmlns”属性替换为“noNSxml”才能正确解析。如果你想重用它,它建议你然后 ti put buck xmlns。

【讨论】:

【参考方案3】:

可以将默认命名空间重命名并进行查询,而不是将文件作为文本处理并进行修改。详情在this answer,附代码。

【讨论】:

以上是关于KissXML 不返回 xpath 查询的值的主要内容,如果未能解决你的问题,请参考以下文章

XML 解析 - 使用 KissXML 和 XPath 将属性分组到 nsdictionary

KissXML 不返回字符串

使用 KissXML 处理 wcf Rest Web 服务 - 我应该如何处理命名空间问题

金蝶KIS旗舰版提示:所选账套无效,无法建立数据库连接

使用 xpath 获取 xsi:type 的值 [关闭]

各种iOS开源类库