Kotlin - 使用 simpleXML 解析 xml 内联列表
Kotlin - parsing xml inline list with simpleXML
我正在尝试使用 kotlin 中的简单xml 解析 rss 提要。
饲料是 top podcasts feed from itunes
返回的数据具有以下结构:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Top Audio Podcasts</title>
<link>https://rss.itunes.apple.com/api/v1/us/podcasts/top-podcasts/all/10/explicit.rss</link>
<lastBuildDate>Fri, 13 Jul 2018 01:36:19 -0700</lastBuildDate>
<atom:link rel="self" type="application/rss+xml" href="https://rss.itunes.apple.com/api/v1/us/podcasts/top-podcasts/all/10/explicit.rss"/>
<atom:link rel="alternate" type="text/html" href="https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewTop?genreId=26&popId=28"/>
<description>iTunes Store : Top Audio Podcasts</description>
<category>iTunes Store</category>
<copyright>Copyright © 2018 Apple Inc. All rights reserved.</copyright>
<item>
<title>The Wilderness - Crooked Media</title>
<category domain="">Crooked Media</category>
<link>https://itunes.apple.com/us/podcast/the-wilderness/id1408796715?mt=2</link>
<guid>https://itunes.apple.com/us/podcast/the-wilderness/id1408796715?mt=2</guid>
<description>The Wilderness</description>
<category>podcast</category>
<category>News & Politics</category>
<category>Podcasts</category>
<category>Society & Culture</category>
<category>History</category>
<pubDate>Fri, 6 Jul 2018 00:00:00 +0000</pubDate>
</item>
<item>
<title>Aaron Mahnke's Cabinet of Curiosities - HowStuffWorks & Aaron Mahnke</title>
<category domain="https://itunes.apple.com/us/artist/howstuffworks-aaron-mahnke/284341002?mt=2">HowStuffWorks & Aaron Mahnke</category>
<link>https://itunes.apple.com/us/podcast/aaron-mahnkes-cabinet-of-curiosities/id1396546917?mt=2</link>
<guid>https://itunes.apple.com/us/podcast/aaron-mahnkes-cabinet-of-curiosities/id1396546917?mt=2</guid>
<description>Aaron Mahnke's Cabinet of Curiosities</description>
<category>podcast</category>
<category>History</category>
<category>Podcasts</category>
<category>Society & Culture</category>
<pubDate>Tue, 10 Jul 2018 00:00:00 +0000</pubDate>
</item>
</channel>
</rss>
我关心的部分是项目标签包含的播客列表。
模特类我长这样:
@Root(name = "channel", strict = false)
data class Chart @JvmOverloads constructor(
@field:ElementList(entry = "item", inline = true)
@param:ElementList(entry = "item", inline = true)
val podcasts: List<Entry>? = null)
@Root(name = "item", strict = false)
data class Entry @JvmOverloads constructor(
@field:Element(name = "description")
@param:Element(name = "description")
val title: String? = null,
@field:Element(name = "category")
@param:Element(name = "category")
val artist: String? = null,
@field:Element(name = "guid")
@param:Element(name = "guid")
val guid: String? = null)
我有一个简单的单元测试,它从文件中加载 xml,将其传递给简单的xml 反序列化器,然后将输出与某些预期模型进行比较。
在我运行测试的那一刻我得到一个异常:
org.simpleframework.xml.core.ValueRequiredException: Unable to satisfy @org.simpleframework.xml.ElementList(entry=item, inline=true, data=false, name=, type=void, required=true, empty=true) on field 'podcasts' private final java.util.List Chart.podcasts for class Chart at line 2
将 required = false 添加到 @ElementList 注释可消除此错误,但列表的反序列化器 returns null。
我最好的猜测是反序列化器找不到项目列表,尽管根据我对@ElementList 的理解,使用输入字段应该允许它找到标签。
此代码的用例是形成 Android 应用程序的网络层,该应用程序依赖 Retrofit2 进行 REST 调用。
感谢您对此提供的任何帮助。
注意:@Param 和@Field 声明的使用是为了对抗不同的异常,
我找到了解决办法。
所以第一个问题是我的根元素不是代表频道标签的图表,我需要一个包装器 class,我称之为 ChartFeed 来代表 rss 标签。
我通过在图表 object 上为标题标签添加一个元素来实现这一点,这也是找不到的。
我完成的数据class是这样的:
@Root(name = "rss", strict = false)
data class ChartFeed(
@field:Element(name = "channel")
@param:Element(name = "channel")
val chart: Chart? = null)
@Root(name = "channel", strict = false)
data class Chart @JvmOverloads constructor(
@field:ElementList(entry = "item", inline = true)
@param:ElementList(entry = "item", inline = true)
val podcasts: List<Entry>? = null)
@Root(name = "item", strict = false)
data class Entry @JvmOverloads constructor(
@field:Path("description")
@field:Text(required = false)
@param:Path("description")
@param:Text(required = false)
val title: String? = null,
@field:Path("category")
@field:Text(required = false)
@param:Path("category")
@param:Text(required = false)
val artist: String? = null,
@field:Element(name = "guid")
@param:Element(name = "guid")
val guid: String? = null)
我已经将几个 fields/params 的 @Element 标签更改为 @Path 和 @Text 的组合,这是因为频道和项目 xml objects重用导致此异常的相同标签:
org.simpleframework.xml.core.PersistenceException: Element 'category' is already used with @org.simpleframework.xml.Element(name=category, type=void, data=false, required=true) on field 'artist' private final java.lang.String Entry.artist at line 18
我用的方案很详细here
我正在尝试使用 kotlin 中的简单xml 解析 rss 提要。
饲料是 top podcasts feed from itunes
返回的数据具有以下结构:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Top Audio Podcasts</title>
<link>https://rss.itunes.apple.com/api/v1/us/podcasts/top-podcasts/all/10/explicit.rss</link>
<lastBuildDate>Fri, 13 Jul 2018 01:36:19 -0700</lastBuildDate>
<atom:link rel="self" type="application/rss+xml" href="https://rss.itunes.apple.com/api/v1/us/podcasts/top-podcasts/all/10/explicit.rss"/>
<atom:link rel="alternate" type="text/html" href="https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewTop?genreId=26&popId=28"/>
<description>iTunes Store : Top Audio Podcasts</description>
<category>iTunes Store</category>
<copyright>Copyright © 2018 Apple Inc. All rights reserved.</copyright>
<item>
<title>The Wilderness - Crooked Media</title>
<category domain="">Crooked Media</category>
<link>https://itunes.apple.com/us/podcast/the-wilderness/id1408796715?mt=2</link>
<guid>https://itunes.apple.com/us/podcast/the-wilderness/id1408796715?mt=2</guid>
<description>The Wilderness</description>
<category>podcast</category>
<category>News & Politics</category>
<category>Podcasts</category>
<category>Society & Culture</category>
<category>History</category>
<pubDate>Fri, 6 Jul 2018 00:00:00 +0000</pubDate>
</item>
<item>
<title>Aaron Mahnke's Cabinet of Curiosities - HowStuffWorks & Aaron Mahnke</title>
<category domain="https://itunes.apple.com/us/artist/howstuffworks-aaron-mahnke/284341002?mt=2">HowStuffWorks & Aaron Mahnke</category>
<link>https://itunes.apple.com/us/podcast/aaron-mahnkes-cabinet-of-curiosities/id1396546917?mt=2</link>
<guid>https://itunes.apple.com/us/podcast/aaron-mahnkes-cabinet-of-curiosities/id1396546917?mt=2</guid>
<description>Aaron Mahnke's Cabinet of Curiosities</description>
<category>podcast</category>
<category>History</category>
<category>Podcasts</category>
<category>Society & Culture</category>
<pubDate>Tue, 10 Jul 2018 00:00:00 +0000</pubDate>
</item>
</channel>
</rss>
我关心的部分是项目标签包含的播客列表。
模特类我长这样:
@Root(name = "channel", strict = false)
data class Chart @JvmOverloads constructor(
@field:ElementList(entry = "item", inline = true)
@param:ElementList(entry = "item", inline = true)
val podcasts: List<Entry>? = null)
@Root(name = "item", strict = false)
data class Entry @JvmOverloads constructor(
@field:Element(name = "description")
@param:Element(name = "description")
val title: String? = null,
@field:Element(name = "category")
@param:Element(name = "category")
val artist: String? = null,
@field:Element(name = "guid")
@param:Element(name = "guid")
val guid: String? = null)
我有一个简单的单元测试,它从文件中加载 xml,将其传递给简单的xml 反序列化器,然后将输出与某些预期模型进行比较。
在我运行测试的那一刻我得到一个异常:
org.simpleframework.xml.core.ValueRequiredException: Unable to satisfy @org.simpleframework.xml.ElementList(entry=item, inline=true, data=false, name=, type=void, required=true, empty=true) on field 'podcasts' private final java.util.List Chart.podcasts for class Chart at line 2
将 required = false 添加到 @ElementList 注释可消除此错误,但列表的反序列化器 returns null。
我最好的猜测是反序列化器找不到项目列表,尽管根据我对@ElementList 的理解,使用输入字段应该允许它找到标签。
此代码的用例是形成 Android 应用程序的网络层,该应用程序依赖 Retrofit2 进行 REST 调用。
感谢您对此提供的任何帮助。
注意:@Param 和@Field 声明的使用是为了对抗不同的异常,
我找到了解决办法。
所以第一个问题是我的根元素不是代表频道标签的图表,我需要一个包装器 class,我称之为 ChartFeed 来代表 rss 标签。
我通过在图表 object 上为标题标签添加一个元素来实现这一点,这也是找不到的。
我完成的数据class是这样的:
@Root(name = "rss", strict = false)
data class ChartFeed(
@field:Element(name = "channel")
@param:Element(name = "channel")
val chart: Chart? = null)
@Root(name = "channel", strict = false)
data class Chart @JvmOverloads constructor(
@field:ElementList(entry = "item", inline = true)
@param:ElementList(entry = "item", inline = true)
val podcasts: List<Entry>? = null)
@Root(name = "item", strict = false)
data class Entry @JvmOverloads constructor(
@field:Path("description")
@field:Text(required = false)
@param:Path("description")
@param:Text(required = false)
val title: String? = null,
@field:Path("category")
@field:Text(required = false)
@param:Path("category")
@param:Text(required = false)
val artist: String? = null,
@field:Element(name = "guid")
@param:Element(name = "guid")
val guid: String? = null)
我已经将几个 fields/params 的 @Element 标签更改为 @Path 和 @Text 的组合,这是因为频道和项目 xml objects重用导致此异常的相同标签:
org.simpleframework.xml.core.PersistenceException: Element 'category' is already used with @org.simpleframework.xml.Element(name=category, type=void, data=false, required=true) on field 'artist' private final java.lang.String Entry.artist at line 18
我用的方案很详细here