客户希望我在他的网站上添加天气预报。官方天气报告是一个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"
表示'今天',index="1"
表示'明天'。客户需要7天的outlook。
因此,目前我需要从所有XML数据中确定日期、图标代码(用于漂亮的图片)和Precis(通常是单个单词或短语)、probability_of_precipitation(会下雨吗?)和时间。其余的我可以扔掉。
在另一个具有类似结构的文件中,有一个长格式预测页面的另一个版本。
我已经能够访问第一行(aac
和description
)的属性,但我需要帮助的是如何访问该行下的预测周期元素。其他地区也有forecast-period
元素,我们不想访问。
我使用ColdFusion XmlSearch/XPATH表达式
进入XML文件的这一部分XmlSearch(IDN10064XML, "//area[@aac='NSW_PT123']")
我的问题是。在上面的示例代码中,(我无法控制-这是政府提供的)我如何创建一个变量来给我结果
"Clear."
从上面的精确元素?"5%"
从降水要素的概率?"2"
从forecast_icon_code元素?
<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")>
返回这个结构体:
{
"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,然后使用常规的结构/数组处理。
你可以在Adobe ColdFusion中使用1行代码将XML转换为JSON。
<cfset myJSONObject = createObject("java","org.json.XML").toJSONObject(XMLText)>
<cfdump var="#myJSONObject#">
更多示例,查看这里的示例CFML:https://gist.github.com/JamoCA/00bb362672f772fab56d26f3e01ad3fa