用于GPX文件的Delphi免费XML解析器/ Reader

时间:2011-12-02 09:12:44

标签: xml delphi parsing gpx

我正在为Delphi中的GPX文件寻找一个易于使用的XML解析器/ Reader,并且想知道是否有人可以推荐一个或者我应该使用Delphi自己的XML数据绑定/ XML文档?

感谢

科林

5 个答案:

答案 0 :(得分:3)

NativeXml

这是一个用于读写XML文档的小型本机Delphi实现。它提供了一种完全面向对象的方法来处理XML文件,具有明确定义的和以Delphi为重点的属性,事件和方法。

您可以使用此代码从/向文件,流或字符串读取和写入XML文档。加载例程生成可用于动态显示加载进度的事件。

NativeXML Website

答案 1 :(得分:3)

您可以使用Delphi的工具“XML mapper” 在我的博客上,you can find the article“加载GPX文件(XML)和数据访问”,解释了如何使用此工具(XML Mapper)。示例创建结构以加载GPX文件。

enter image description here

您可以找到其他类似帖子,例如使用此工具生成KML文件的"Generate KML files routes; Tracks on Google Maps"

该网页最初是西班牙语,但您可以使用Google翻译(在页面右侧)。您也可以下载样本的源代码并查看/测试它。

问候。

答案 2 :(得分:2)

OmniXML

它是免费的(MPL 1.1),速度相当快,并且实现了DOM Level 1规范以及一些MS扩展。

StackOverflow上有一些OmniXML examples

答案 3 :(得分:1)

TNativeXML的替代方式。

你显然可以从TNativeXml派生专门的类,但在我的代码中我使用了一个帮助类:

unit uHelper;

interface

uses
  SysUtils,
  Classes,
  NativeXml;

const
  // Do not localize these
  sNamespace  = 'http://www.topografix.com/GPX/1/1';
  sVersion = '1.1';
  sCreator = 'SwathGen';
  sSchemaInstance = 'http://www.w3.org/2001/XMLSchema-instance';
  sSchemaLocation = sNamespace+' '+
                    'http://www.topografix.com/GPX/1/1/gpx.xsd';

resourcestring
  sNoGpxRoot       = '<%s> has no gpx root !';
  sWrongGpxXmlns   = '<%s> root has a wrong xmlns attribute';
  sWrongGpxVersion = '<%s> is not a version "1.1" gpx file !';

type
  EGpxException = class(Exception)

  end;

type
  TGpxHelper = class helper for TNativeXml
  private
    function GetMetadataNode: TXmlNode;
    function GetWaypointNodes: TsdNodeList;
    function GetRouteNodes: TsdNodeList;
    function GetTrackNodes: TsdNodeList;
    function GetExtensionsNode: TXmlNode;
  public
    constructor CreateGpx(AOwner: TComponent);

    procedure NewGpx;

    procedure NodesAdd(ANodes: array of TXmlNode); overload;

    procedure AssignToStrings(AStrings:TStrings);

    function Element(const AName: string): TXmlNode;

    // File IO
    procedure LoadGpxFromFile(const AFileName: string);
    procedure SaveGpxToFile(const AFileName: string);

    property Metadata:TXmlNode read GetMetadataNode;
    property Waypoints:TsdNodeList read GetWaypointNodes;
    property Routes:TsdNodeList read GetRouteNodes;
    property Tracks:TsdNodeList read GetTrackNodes;
    property Extensions:TXmlNode read GetExtensionsNode;
  end;

  TGpxNodeHelper = class helper for TXmlNode
    function Element(const AName: string): TXmlNode;
  end;

implementation

{ TGpxHelper }

procedure TGpxHelper.AssignToStrings(AStrings:TStrings);
var
  lXmlFormat: TXmlFormatType;
  lIndentString: string;
begin
  // Save states
  lXmlFormat := XmlFormat;
  lIndentString := IndentString;

  XmlFormat := xfReadable;
  IndentString := '  ';

  AStrings.Text := WriteToString;

  // Restore states
  XmlFormat := lXmlFormat;
  IndentString := lIndentString;
end;

constructor TGpxHelper.CreateGpx(AOwner: TComponent);
begin
  inherited Create(AOwner);
  //
  NewGpx;
end;

function TGpxHelper.Element(const AName: string): TXmlNode;
begin
  Result := Root.Element(AName);
end;

function TGpxHelper.GetExtensionsNode: TXmlNode;
begin
  Result := Element('extensions');
end;

function TGpxHelper.GetMetadataNode: TXmlNode;
begin
  Result := Element('metadata');
end;

function TGpxHelper.GetRouteNodes: TsdNodeList;
begin
  Result := TsdNodeList.Create(False);

  Root.NodesByName('rte', Result);
end;

function TGpxHelper.GetTrackNodes: TsdNodeList;
begin
  Result := TsdNodeList.Create(False);

  Root.NodesByName('trk', Result);
end;

function TGpxHelper.GetWaypointNodes: TsdNodeList;
begin
  Result := TsdNodeList.Create(False);

  Root.NodesByName('wpt', Result);
end;

procedure TGpxHelper.LoadGpxFromFile(const AFileName: string);
var
  lGpx: TNativeXml;
  lFileName: TFileName;
begin
  lFileName := ExtractFileName(AFileName);

  lGpx := TNativeXml.Create(Self);

  lGpx.LoadFromFile(AFileName);

  try
    if lGpx.Root.Name<>'gpx' then
      raise EGpxException.CreateFmt(sNoGpxRoot,[lFileName])
    else if lGpx.Root.AttributeValue[Root.AttributeIndexByName('xmlns')]<>sNamespace then
      raise EGpxException.CreateFmt(sWrongGpxXmlns,[lFileName])
    else if lGpx.Root.AttributeValue[Root.AttributeIndexByName('version')]<>sVersion then
      raise EGpxException.CreateFmt(sWrongGpxVersion,[lFileName])
    else
      Self.ReadFromString(lGpx.WriteToString) // <<<
  finally
    lGpx.Free
  end;
end;

procedure TGpxHelper.NewGpx;
begin
  New;

  Root.Name := 'gpx';

  NodesAdd(
    [
      AttrText('xmlns', sNamespace),
      AttrText('version', sVersion),
      AttrText('creator', sCreator),
      AttrText('xmlns:xsi',sSchemaInstance),
      AttrText('xsi:schemaLocation', sSchemaLocation),

      // Metadata
      NodeNew('metadata',
        [
          NodeNewAttr('bounds',
            [
              AttrText('minlat','90.00000000'),
              AttrText('minlon','180.00000000'),
              AttrText('maxlat','-90.00000000'),
              AttrText('maxlon','-180.00000000')
            ]
          ),
          NodeNew('extensions')
        ]
      ),

      // Waypoints

      // Routes

      // Tracks

      NodeNew('extensions')
    ]
  );
end;

procedure TGpxHelper.NodesAdd(ANodes: array of TXmlNode);
begin
  Root.NodesAdd(ANodes);
end;

procedure TGpxHelper.SaveGpxToFile(const AFileName: string);
begin
  ChangeFileExt(AFileName,'gpx');

  SaveToFile(AFileName);  
end;

{ TGpxNodeHelper }

function TGpxNodeHelper.Element(const AName: string): TXmlNode;
begin
  Result := NodeByName(UTF8String(AName));
end;

end.

使用uHelper装置的实际样本:

unit ufrmMain;

interface

uses
  NativeXml,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, SynEdit, SynMemo, SynEditHighlighter, SynHighlighterXML,
  SynEditMiscClasses, SynEditSearch, ComCtrls;

type
  TMainForm = class(TForm)
    BtnNew: TButton;
    BtnLoad: TButton;
    OpenDialog: TOpenDialog;
    BtnSave: TButton;
    SaveDialog: TSaveDialog;
    Memo: TSynMemo;
    XMLSyn: TSynXMLSyn;
    Search: TSynEditSearch;
    StatusBar: TStatusBar;
    procedure FormCreate(Sender: TObject);
    procedure BtnLoadClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure BtnSaveClick(Sender: TObject);
    procedure BtnNewClick(Sender: TObject);
  private
    FGpx: TNativeXml;

    procedure ShowGpxInfo;
    procedure UpdateControls;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

uses
  Math,
  uHelper;

{$R *.dfm}

procedure TMainForm.BtnLoadClick(Sender: TObject);
begin
  OpenDialog.FileName := '';

  if OpenDialog.Execute then
  begin
    FGpx.LoadGpxFromFile(OpenDialog.FileName);

    UpdateControls;
    ShowGpxInfo
  end;
end;

procedure TMainForm.BtnNewClick(Sender: TObject);
begin
  FGpx.NewGpx;

  UpdateControls;
end;

procedure TMainForm.BtnSaveClick(Sender: TObject);
begin
  SaveDialog.FileName := '';

  if SaveDialog.Execute then
  begin
    FGpx.SaveGpxToFile(SaveDialog.FileName);
  end;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FGpx := TNativeXml.CreateGpx(Self);
end;

procedure TMainForm.FormShow(Sender: TObject);
begin
  UpdateControls;
end;

procedure TMainForm.ShowGpxInfo;
const
  cLF = #10#13;
  cMsg  = 'metadata node count : %u'+cLF+
          'wpt node count : %u'+cLF+
          'rte node count : %u'+cLF+
          'trk node count : %u'+cLF+
          'extensions node count : %u';
var
  lMetadataCount: Integer;
  lWaypointsCount: Integer;
  lRoutesCount: Integer;
  lTracksCount: Integer;
  lExtensions: Integer;
begin
  lMetadataCount := IfThen(Assigned(FGpx.Metadata),1,0); 

  with FGpx.Waypoints do
  try
    lWaypointsCount := Count;
  finally
    Free
  end;

  with FGpx.Routes do
  try
    lRoutesCount := Count;
  finally
    Free
  end;

  with FGpx.Tracks do
  try
    lTracksCount := Count;
  finally
    Free
  end;

  lExtensions := IfThen(Assigned(FGpx.Extensions),1,0); 

  ShowMessage(Format(cMsg,[lMetadataCount,lWaypointsCount,lRoutesCount,lTracksCount,lExtensions]))
end;

procedure TMainForm.UpdateControls;
begin
  FGpx.AssignToStrings(Memo.Lines); // <<<
end;

end.

答案 4 :(得分:0)

您可以使用SimpleStorage

访问Gpx文件的示例代码:

interface

uses
  ...
  Cromis.SimpleStorage, ...

type
  TMainForm = class(TForm)
    ...
    MmGpx: TMemo;
    BtnLoad: TButton;
    OpenDialog: TOpenDialog;
    ...
  private
    FGpxStorage: ISimpleStorage;
  protected
    procedure ShowGpx;
  end;

...

implementation

procedure TMainForm.BtnLoadClick(Sender: TObject);
begin
  if OpenDialog.Execute then
    FGpxStorage := StorageFromFile(OpenDialog.FileName); // <<<
    ShowGpx;
  end;
end;

procedure TMainForm.ShowGpx;
begin
  MmGpx.Lines.Text := FGpxStorage.Content(True); // <<<
end;

此外,您仍然可以找到使用hereSimpleStorage模板,从头开始生成合规的新Gpx文件。