java—使用dsm(声明流Map)将xml文件解组到对象

sycxhyv7  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(394)

我需要将xml转换为java对象。为此,我选择了声明流Map(declarativestream mapping,dsm),但不清楚如何将带有属性的嵌套元素Map到列表。具体来说,如何在yaml文件中描述下一篇文章:

<categories>
  <category id="1" parentId="2">Lorum Ipsum</category>
</categories>

我尝试了所有的选择,但都失败了。
下面是我正在运行的代码片段。
电力需求侧管理(yaml):

result:
  type: object
  path: /catalog/shop
  fields:
    name:
      path: name
    company:
      path: company
    url:
      path: url
    platform:
      path: platform
    agency:
      path: agency
    email:
      path: email
    currencies:
      type: array
      path: currencies/currency
      fields:
        id:
          xml:
            attribute: true
        rate:
          xml:
            attribute: true
    categories:
      type: array
      path: categories/category
      fields:
        id:
          xml:
            attribute: true
        parentId:
          xml:
            attribute: true
    deliveryOptions:
      type: array
      path: delivery-options/option
      fields:
        cost:
          xml:
            attribute: true
        days:
          xml:
            attribute: true
    offers:
      type: array
      path: offers/offer
      fields:
        id:
          xml:
            attribute: true
        available:
          xml:
            attribute: true
        type:
          xml:
            attribute: true
        param:
          path: param
        offer:
          fields:
            url:
              path: url
            price:
              path: price

# shortened due to length

要转换的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE yml_catalog SYSTEM "shops.dtd">
    <catalog date="2019-09-08 22:37">
      <shop>
        <name>company name</name>
        <company>Microsoft</company>
        <url>https://microsoft.com</url>
        <platform>woefjwoefi</platform>
        <agency>Agent</agency>
        <email>billi@ms.com</email>
        <currencies>
          <currency id="USD" rate="1"/>
        </currencies>
        <categories>
          <category id="398" parentId="198">Lorum Ipsum</category>
          <category id="409">Uncategorized</category>
        </categories>
        <offers>
          <offer id="2016" available="true" type="vendor.model">
            <url>https://ms.com/id/1</url>
            <price>35.00</price>
            <currencyId>USD</currencyId>
            <categoryId>168</categoryId>
            <picture>https://ms.com/image/cache/catalog/8987-600x600.jpg</picture>
            <store>true</store>
            <pickup>true</pickup>
            <delivery>true</delivery>
            <vendor>MS</vendor>
            <vendorCode>MS-10111</vendorCode>
            <model>plasdf</model>
            <downloadable>false</downloadable>
            <param name="Weight">0.0</param>
          </offer>
          <offer id="2017" available="true" type="vendor.model">
            <url>https://ms.com/id/2</url>
            <price>250.00</price>
            <currencyId>USD</currencyId>
            <categoryId>201</categoryId>
            <picture>https://ms.com/image/cache/catalog/aktiv-600x600.png</picture>
            <store>true</store>
            <pickup>true</pickup>
            <delivery>true</delivery>
            <vendor>MS</vendor>
            <vendorCode>MS03238</vendorCode>
            <model>woeifjwoef wefw fw we</model>
            <description>wiefwof wef</description>
            <downloadable>false</downloadable>
            <weight>30.0</weight>
            <param name="Weight">30.0</param>
          </offer>
        </offers>
      </shop>
    </catalog>

java 语:

public class Shop {
  private String name;
  private String company;
  private String url;
  private String platform;
  private String agency;
  private String email;
  private List<Currencies> currencies;
  private List<Categories> categories;
  private List<DeliveryOptions> deliveryOptions;
  private List<Offers> offers;
  // getters/setters
}

class Currencies {
  // getters/setters
}

class Categories {
  // getters/setters
}

class DeliveryOptions {
  // getters/setters
}

class Offers {
  // getters/setters
}

输出:

{
  "name" : "company name",
  "company" : "Microsoft",
  "url" : "https://microsoft.com",
  "platform" : "woefjwoefi",
  "agency" : "Agent",
  "email" : "billi@ms.com",
  "currencies" : null,
  "categories": null,
  "deliveryOptions": null,
  "offers": null
}
41zrol4v

41zrol4v1#

我做了一些轻微的缩进调整,你的dsm配置文件工作得很好。
帝斯曼yml

result:
  type: object
  path: /catalog/shop
  fields:
    name:
      path: name
    company:
      path: company
    url:
      path: url
    platform:
      path: platform
    agency:
      path: agency
    email:
      path: email
    currencies:
      type: array
      path: currencies/currency
      fields:
        id:
          xml:
            attribute: true
        rate:
          xml:
            attribute: true
    categories:
      type: array
      path: categories
      xml:
        path: categories/category
      fields:
        name:
          path: ./
        id:
          xml:
            attribute: true
        parentId:
          xml:
            attribute: true
    deliveryOptions:
      type: array
      path: delivery-options/option
      fields:
        cost:
          xml:
            attribute: true
        days:
          xml:
            attribute: true
    offers:
      type: array
      path: offers/offer
      fields:
        id:
          xml:
            attribute: true
        available:
          xml:
            attribute: true
        type:
          xml:
            attribute: true
        param:
          path: param
        url: default
        price: default
        currencyId: default
        categoryId: default

输出:

{
  "name" : "company name",
  "company" : "Microsoft",
  "url" : "https://microsoft.com",
  "platform" : "woefjwoefi",
  "agency" : "Agent",
  "email" : "billi@ms.com",
  "currencies" : [ {
    "id" : "USD",
    "rate" : 1
  } ],
  "categories" : [ {
    "id" : 398,
    "parentId" : 198,
    "name" : "Lorum Ipsum"
  }, {
    "id" : 409,
    "parentId" : null,
    "name" : "Uncategorized"
  } ],
  "deliveryOptions" : null,
  "offers" : [ {
    "id" : "2016",
    "available" : true,
    "type" : "vendor.model",
    "url" : "https://ms.com/id/1",
    "price" : 35.0,
    "currencyId" : "USD",
    "categoryId" : "168",
  }, {
    "id" : "2017",
    "available" : true,
    "type" : "vendor.model",
    "url" : "https://ms.com/id/2",
    "price" : 250.0,
    "currencyId" : "USD",
    "categoryId" : "201",

  } ]
}

这是我用来测试它的代码:

@Test
public void dsmParsing() throws IOException {

    InputStream is = new FileInputStream("src/main/resources/dsm.yml");

    DSMBuilder builder = new DSMBuilder(is);
    DSM dsm = builder.setType(DSMBuilder.TYPE.XML).create(Shop.class);
    Shop shop = (Shop) dsm.toObject(new File("src/main/resources/shop.xml"));

    ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();

    System.out.println(ow.writeValueAsString(shop));
}

要回答有关具有属性的嵌套元素的问题,必须考虑到在使用此定义时:

categories:
  type: array
  path: categories/category

当你定义 fields 您将描述元素 <category> .
在下面的示例中,属性 id 以及 parentId 将在 fields 段作为属性,但得到实际值 category 元素,则需要引用当前路径 ./ . 如果有子元素,只需在 fields 段。
xml格式

<categories>
   <category id="398" parentId="198">Lorum Ipsum</category>
 </categories>

需求侧管理

categories:
  type: array
  path: categories/category
  fields:
    name: ## you could call it 'value' or whatever you want
      path: ./
    id:
      xml:
        attribute: true
    parentId:
      xml:
        attribute: true

下一个例子很有趣:
xml格式

<offers attr1="abc" attr2="def">
    <offer id="2016" available="true">
        <url>https://ms.com/id/1</url>
    </offer>
</offers>

首先,您需要另一个pojo来正确表示 offers 及其属性:
商店

public class Shop {
  ...
  OffersList offers; // this attribute's name needs to match the one used in the dsm descriptor
}

新类报价表

public class OffersList {
  String attr1;
  String attr2;
  List<Offers> offer; // this attribute's name needs to match the one used in the dsm descriptor
}

最后,dsm将如下所示:

offers: ## name should match with Shop's attribute 'offers' (OffersList)
  type: object ## now offers is an object, is mandatory to define 'fields'
  path: offers  ## focus is on the <offers> element
  fields:
    attr1:
      xml:
        attribute: true
    attr2:
      xml:
        attribute: true
    offer:   ## name should match with OffersList's attribute 'offer'
      type: array
      path: ../offers/offer  ## will go back a level to indicate <offers> <offer> should be parsed as an array
      fields:
        id:
          xml:
            attribute: true
        available:
          xml:
            attribute: true
        url:
          path: url

输出

"offers" : {
    "attr1" : "abc",
    "attr2" : "def",
    "offer" : [ {
      "id" : "2016",
      "available" : true,
      "url" : "https://ms.com/id/1",
    } ]
  }

相关问题