📄 FormatXML
FormatXML 是 ipapi.co-skills Go SDK 中的响应格式常量之一,用于将 API 响应指定为 XML 格式。由于 SDK 内置的 IPInfo 结构体默认按 JSON 解码,XML 格式需通过 GetIPInfoRaw 获取原始字节后自行处理。
🎨 一图抵千言
下图展示了 SDK 在收到带 format=xml 的请求时,如何在内部分支中路由到 XML 处理路径,并以原始字节形式返回给调用方:
⚠️ 内部方法不可直接调用
上图中的 newGetRequest / setHeaders / doRequest / mapStatusCodeToError 均为 SDK 未导出的内部方法,仅用于说明请求生命周期原理。用户代码只能通过 GetIPInfoRaw 等公开方法间接触发该流程,无法也无需直接调用这些内部函数。
📌 定义
go
// FormatXML 表示 XML 响应格式,需通过 GetIPInfoRaw 获取原始字节。
const FormatXML Format = "xml"底层类型 Format 是基于 string 的自定义类型,与其它格式常量一同声明在同一常量块中:
go
// Format 表示 API 请求的响应格式。
type Format string
const (
FormatJSON Format = "json"
FormatJSONP Format = "jsonp"
FormatXML Format = "xml"
FormatCSV Format = "csv"
FormatYAML Format = "yaml"
)FormatXML 同时注册在 SDK 内部的 validFormats 白名单中,因此通过 ValidateFormat 校验时会返回合法。
📖 说明
🏷️ 类别:格式常量(Format)
🎯 适用场景:
- 🏢 需要与遗留的 SOAP / XML 数据管线或企业内部 XML 接口对接时
- 🗂️ 需要用
encoding/xml标准库将响应反序列化进自定义 Go 结构体时 - 📊 需要以自描述标签形式呈现字段名,便于跨系统、跨语言解析时
💡 关键特性:
- ✅ 以 XML 标签包裹字段,结构自描述、可被通用 XML 解析器读取
- ✅ 与
GetIPInfoRaw搭配使用,获取原始 XML 字节流 - ✅ 通过
ValidateFormat(FormatXML)校验为合法格式 - ⚠️ SDK 的
GetIPInfo等方法默认按 JSON 解析为*IPInfo结构体;若传入FormatXML,应使用GetIPInfoRaw获取原始文本,再用encoding/xml自行解析 - ⚠️ 传入非法格式会触发
ErrInvalidFormat错误
🐞 调试技巧:如何确认服务端真的返回了 XML
当解析结果不符合预期时,可按以下三步排查:
- 先看原始字节:把
GetIPInfoRaw返回的[]byte直接打印或落盘,确认首行是<?xml version="1.0" ...?>,而不是 JSON 的{或 HTML 错误页。 - 核对结构体标签:
encoding/xml严格按xml:"tag"匹配服务端标签名,字段名拼写、大小写、下划线(如country_name)必须一一对应,否则静默得到零值。 - 留意错误页:若触限或 key 非法,服务端可能返回非 XML 文本,此时
xml.Unmarshal会报语法错;应先检查err与 HTTP 状态码,对照mapStatusCodeToError与ErrInvalidKey判断根因。
🛠️ 用法 / 示例
1️⃣ 获取原始 XML 响应
使用 GetIPInfoRaw 获取指定 IP 的 XML 格式原始字节:
go
package main
import (
"context"
"fmt"
"log"
"github.com/cyberspacesec/ipapi.co-skills/pkg/ipapi"
)
func main() {
client := ipapi.NewClient()
// 以 XML 格式查询 8.8.8.8 的全部字段
raw, err := client.GetIPInfoRaw(context.Background(), "8.8.8.8", string(ipapi.FormatXML))
if err != nil {
log.Fatalf("查询失败: %v", err)
}
fmt.Println(string(raw))
}输出示例:
xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<ip>8.8.8.8</ip>
<network>8.8.8.0/24</network>
<version>IPv4</version>
<city>Mountain View</city>
<region>California</region>
<region_code>CA</region_code>
<country>US</country>
<country_name>United States</country_name>
<country_code>US</country_code>
<country_code_iso3>USA</country_code_iso3>
<country_capital>Washington</country_capital>
<latitude>37.4056</latitude>
<longitude>-122.0775</longitude>
</response>2️⃣ 用 encoding/xml 解析进自定义结构体
GetIPInfoRaw 返回的是原始字节,可借助标准库 encoding/xml 反序列化为你自定义的结构体:
go
package main
import (
"context"
"encoding/xml"
"fmt"
"log"
"github.com/cyberspacesec/ipapi.co-skills/pkg/ipapi"
)
// 按需挑选字段,标签名与服务端 XML 标签一一对应。
type ipResult struct {
IP string `xml:"ip"`
City string `xml:"city"`
Region string `xml:"region"`
Country string `xml:"country"`
CountryName string `xml:"country_name"`
Latitude float64 `xml:"latitude"`
Longitude float64 `xml:"longitude"`
}
func main() {
client := ipapi.NewClient()
raw, err := client.GetIPInfoRaw(context.Background(), "8.8.8.8", string(ipapi.FormatXML))
if err != nil {
log.Fatalf("查询失败: %v", err)
}
var result ipResult
if err := xml.Unmarshal(raw, &result); err != nil {
log.Fatalf("XML 解析失败: %v", err)
}
fmt.Printf("%s 位于 %s, %s (%.4f, %.4f)\n",
result.IP, result.City, result.CountryName,
result.Latitude, result.Longitude)
}3️⃣ 校验格式合法性
在拼装请求前可主动校验格式常量是否被 SDK 支持:
go
package main
import (
"fmt"
"log"
"github.com/cyberspacesec/ipapi.co-skills/pkg/ipapi"
)
func main() {
if err := ipapi.ValidateFormat(string(ipapi.FormatXML)); err != nil {
log.Fatalf("格式非法: %v", err)
}
fmt.Println("FormatXML 是受支持的响应格式")
}4️⃣ 查询本机出口 IP 的 XML 数据
GetClientIPInfoRaw 同样接受格式参数,可获取调用方(本机)IP 的 XML 信息:
go
package main
import (
"context"
"fmt"
"log"
"github.com/cyberspacesec/ipapi.co-skills/pkg/ipapi"
)
func main() {
client := ipapi.NewClient()
raw, err := client.GetClientIPInfoRaw(context.Background(), string(ipapi.FormatXML))
if err != nil {
log.Fatalf("查询失败: %v", err)
}
fmt.Println(string(raw))
}🔗 相关
- 🧱
Client—— 承载格式请求的客户端结构体 - 📚
Methods——GetIPInfoRaw/GetClientIPInfoRaw等接受格式参数的方法 - 🗃️
Models——IPInfo等数据模型(默认按 JSON 解析) - 🚨
Errors—— 含ErrInvalidFormat等错误定义 - ⚙️
Options——NewClient的配置选项 - 🔎
ValidateFormat—— 格式合法性校验函数