DDEX
介绍
DDEX
是"数字音乐交换"(Digital Data Exchange)的缩写,它是一个全球性的标准化组织,致力于为数字音乐行业提供统一的数据交换标准和协议。
DDEX
格式主要以文本 xml
格式为主,目前行业内主要以 ftp
存储方式进行交换数据。
版本
截至到目前为止,DDEX
格式已经走过多个年头,版本繁多,行业内以 mlc-14
,rdr-15
两个版本为主。
请参考DDEX版本。
解析
因 DDEX
格式部分数据较为原始,为尽量理解该格式,该文章主要以 DDEX
格式各版本 xsd
文件使用 jaxb
方式生成 Java
代码来解析。
在 Maven
项目中引入以下插件,并配置以下三项:
- packageName: 生成的
Java
代码包名前缀。 - source:
DDEX
格式的xsd
文件位置。 - xjbSource:
jaxb
生成限制等,示例如下。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<locale>en</locale>
<arguments>
<arg>-XautoNameResolution</arg>
</arguments>
<packageName>net.ddex.ern</packageName>
<sources>
<source>src/main/resources/ern/341/release-notification.xsd</source>
</sources>
<xjbSources>
<xjbSource>src/main/resources/binding.xjb</xjbSource>
</xjbSources>
</configuration>
</plugin>
<?xml version="1.0" ?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
version="3.0">
<!-- Raise theEnumMemberSizeCap limit -->
<jaxb:bindings>
<jaxb:globalBindings typesafeEnumMaxMembers="8000" typesafeEnumMemberName="generateName"/>
</jaxb:bindings>
</jaxb:bindings>
配置完成后使用 Maven
运行该插件中 xjc
指令即可在 target
目录下找到生成的对应代码,将代码复制到对应项目中即可使用。
代码使用
该章节主要以个人理解编写,不代表官方案例,可能部分理解错误,具体请以实际为准。
- 由
xsd
生成的代码中主要以ObjectFactory
为主要创建形式,示例如下:
// rdr-15 协议中创建 xml 基础对象方法
DeclarationOfSoundRecordingRightsClaimMessage claimMessage = rdrFactory.createDeclarationOfSoundRecordingRightsClaimMessage();
// 头部信息
MessageHeader messageHeader = rdrFactory.createMessageHeader();
// 设置头部信息的其他方法
...
// 将头部信息设置到基础对象中
claimMessage.setMessageHeader(createMessageHeader());
// 设置本次传输的具体资源信息(音频、视频等)
ResourceList resourceList = rdrFactory.createResourceList();
claimMessage.setResourceList(resourceList);
// 创建音频信息
SoundRecording soundRecording = rdrFactory.createSoundRecording();
// 设置音频信息
...
// 将音频添加到资源里
resourceList.getSoundRecording().add(soundRecording);
// 创建视频
Video video = rdrFactory.createVideo();
// 设置音频信息
...
// 将视频添加到资源里
resourceList.getVideo().add(video);
- 使用
jaxb
生成xml
,示例代码如下:
// 以下代码仅用于 jdk8,之后的版本因 jarkata 替换问题,请自行探索
// jaxb 相关类都为 javax.xml.bind 下类
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public static String beanToXml(Object object, String schemaLocation, String prefix) {
StringWriter stringWriter = new StringWriter();
try {
// 根据 xml 基础对象类创建 jaxb context
JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
Marshaller marshaller = jaxbContext.createMarshaller();
//编码格式
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
// 是否格式化生成的xml串
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// 是否生成报文头
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
// 不同版本的 schema 不同,在这里单独设置
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation);
// 定义 namespace 的前缀,prefix 为自己定义的变量
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() {
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if (namespaceUri.equals("http://www.w3.org/2001/XMLSchema-instance")) {
return "xs";
}
return prefix;
}
});
// 因上方设置报文头,所以需要手动添加
stringWriter.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
// 自动转换对象为 xml 文本输出
marshaller.marshal(object, stringWriter);
} catch (Exception e) {
log.error("{}, {}", e.getClass().getSimpleName(), ExceptionUtil.stacktraceToOneLineString(e));
}
return stringWriter.toString();
}
@SuppressWarnings("unchecked")
public static <T> T xmlToBean(Class<T> clazz, String xml) {
// 根据不同类,将 xml 反序列化为不同对象
T xmlObject = null;
try (StringReader stringReader = new StringReader(xml)) {
JAXBContext context = JAXBContext.newInstance(clazz);
// 进行将Xml转成对象的核心接口
Unmarshaller unmarshaller = context.createUnmarshaller();
xmlObject = (T) unmarshaller.unmarshal(stringReader);
} catch (Exception e) {
log.error("{}, {}", e.getClass().getSimpleName(), ExceptionUtil.stacktraceToOneLineString(e));
}
return xmlObject;
}
-
其他
ddex
使用jaxb
中常见问题:- 部分生成的以
JAXBElement<?>
为类型的字段,创建示例如下:
Name performerName = rdrFactory.createName(); performerName.setValue(performerSplit); PartyName performerPartyName = rdrFactory.createPartyName(); performerPartyName.setFullName(performerName); JAXBElement<PartyName> performerElement = rdrFactory.createPartyDescriptorPartyName(performerPartyName); performerElement.setValue(performerPartyName); Artist artist = rdrFactory.createArtist(); artist.getContent().add(performerElement); territory.getDisplayArtist().add(artist);
jaxb
中ddex
中时间,创建示例如下:
GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTime(new Date()); XMLGregorianCalendar xmlDatetime = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar); //本次信息生成时间 messageHeader.setMessageCreatedDateTime(xmlDatetime);
- 部分生成的以