2

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

谢谢

科林

4

5 回答 5

3

NativeXml

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

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

NativeXML 网站

于 2011-12-02T09:32:05.373 回答
3

您可以使用 Delphi 的“XML 映射器”工具。
在我的博客上,您可以找到文章“加载 GPX 文件 (XML) y 访问数据”,该文章解释了如何使用此工具(XML 映射器)。示例创建结构以加载 GPX 文件。

在此处输入图像描述

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

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

问候。

于 2011-12-02T10:19:53.523 回答
2

OmniXML

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

StackOverflow 上有一些OmniXML 示例

于 2011-12-02T10:18:32.097 回答
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.
于 2011-12-04T14:53:09.867 回答
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;

此外,您仍然可以在此处找到使用SimpleStorage从头开始​​生成兼容的新 Gpx 文件的模板。

于 2011-12-04T14:38:10.557 回答