如何使用 Coldfusion 访问 XML 数据

How to access XML data with Coldfusion

一位客户要我在他的网站上添加天气预报。官方天气预报包含在 XML 文件中,我需要帮助才能访问文件中的某些元素。

我可以下载包含网站所需数据的两个 XML 文件,我可以将它们解析为 ColdFusion XML 变量。

我可以从顶层提取我需要的数据,但较低的层级让我有些心痛。 XML 文件包含该州每个位置的天气观测和预报。我们不需要那个 - 我们只想访问有关我客户位置的数据。

这是我正在谈论的 XML 数据的示例

<area aac="NSW_PT123" description="Richmond" type="location" parent-aac="NSW_PW005">
        <forecast-period index="0" start-time-local="2021-10-16T17:00:00+11:00" end-time-local="2021-10-17T00:00:00+11:00" start-time-utc="2021-10-16T06:00:00Z" end-time-utc="2021-10-16T13:00:00Z">
            <element type="forecast_icon_code">2</element>
            <text type="precis">Clear.</text>
            <text type="probability_of_precipitation">5%</text>
        </forecast-period>
        <forecast-period index="1" start-time-local="2021-10-17T00:00:00+11:00" end-time-local="2021-10-18T00:00:00+11:00" start-time-utc="2021-10-16T13:00:00Z" end-time-utc="2021-10-17T13:00:00Z">
            <element type="forecast_icon_code">1</element>
            <element type="air_temperature_minimum" units="Celsius">7</element>
            <element type="air_temperature_maximum" units="Celsius">24</element>
            <text type="precis">Sunny.</text>
            <text type="probability_of_precipitation">0%</text>
        </forecast-period>
        <forecast-period index="2" start-time-local="2021-10-18T00:00:00+11:00" end-time-local="2021-10-19T00:00:00+11:00" start-time-utc="2021-10-17T13:00:00Z" end-time-utc="2021-10-18T13:00:00Z">
            <element type="forecast_icon_code">1</element>
            <element type="air_temperature_minimum" units="Celsius">7</element>
            <element type="air_temperature_maximum" units="Celsius">28</element>
            <text type="precis">Sunny.</text>
            <text type="probability_of_precipitation">5%</text>
        </forecast-period>

在此代码段中,index="0" 表示 'today',index="1" 表示 'tomorrow'。客户想要7天的outlook。

所以目前在所有 XML 数据中我需要确定它是关于哪一天的,图标代码(用于漂亮的图片)和 Precis(通常是一个单词或短语),probability_of_precipitation(会下雨吗?)和时间。剩下的我可以扔掉。

在另一个具有类似结构的文件中,有针对该页面的另一个版本的长格式预测。

我已经能够访问第一行(aacdescription)中的属性,但我需要帮助的是如何访问该行下的预测期元素。所有其他地区也有 forecast-period 个元素,我们不想访问这些元素。

我使用 ColdFusion XmlSearch/XPATH 表达式进入 XML 文件的这一部分

XmlSearch(IDN10064XML, "//area[@aac='NSW_PT123']")

所以这是我的问题。在上面的示例代码中,(我无法控制 - 这是政府提出的)我如何创建一个变量来给我结果

<cffunction name="WeatherForecast" returntype="struct">
  <cfargument name="weatherData" type="xml" required="yes">
  <cfargument name="areaCode" type="string" required="yes">

  <cfset var areas = XmlSearch(weatherData, "//area[@aac='#areaCode#']")>
  <cfif ArrayLen(areas) eq 0>
    <cfthrow message="WeatherForecast: area code #areaCode# not found.">
  </cfif>
  
  <cfset var textOnly = function (node) {
    return node.XmlType == 'ATTRIBUTE' ? node.XmlValue : node.XmlText;
  }>

  <cfreturn {
    icons: XmlSearch(areas[1], "./forecast-period/element[@type='forecast_icon_code']").map(textOnly),
    precis: XmlSearch(areas[1], "./forecast-period/text[@type='precis']").map(textOnly),
    precipitation: XmlSearch(areas[1], "./forecast-period/text[@type='probability_of_precipitation']").map(textOnly)
  }>
</cffunction>

用法:

<cfset IDN10064XML = XmlParse(weatherXml, true)>
<cfset forecast = WeatherForecast(IDN10064XML, "NSW_PT123")>

returns 这个结构:

{
    "PRECIPITATION": ["5%", "0%", "5%"],
    "PRECIS": ["Clear.", "Sunny.", "Sunny."],
    "ICONS": ["2", "1", "1"]
}

每个部分将包含的值与 XML 中 <area><forecast-period> 个元素一样多,按照它们在 XML 中出现的顺序排列。换句话说,forecast.precipitation[1] 指的是“今天”,除非 XML 有可能出现故障(我对此表示怀疑)。

时间属性值之类的东西可以用同样的方法提取:

XmlSearch(areas[1], "./forecast-period/@start-time-local").map(textOnly)

我更喜欢将简单的 XML 转换为 JSON,然后使用常规 struct/array 处理。

您可以使用 1 行代码在 Adob​​e ColdFusion 中将 XML 转换为 JSON。

<cfset myJSONObject = createObject("java","org.json.XML").toJSONObject(XMLText)>
<cfdump var="#myJSONObject#">

有关更多示例,请在此处查看示例 CFML: https://gist.github.com/JamoCA/00bb362672f772fab56d26f3e01ad3fa