1

So I'm transitioning over from C# in Unity, where reflection in XML was quite easy. I wanted to apply the same process in Java to this to a slightly varied version of already existing XML of this type of format:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<imgdir name="0206.img">
  <imgdir name="02060003">
    <imgdir name="info">
      <canvas name="icon" width="32" height="32">
        <vector name="origin" x="0" y="32" />
      </canvas>
      <canvas name="iconRaw" width="32" height="31">
        <vector name="origin" x="0" y="32" />
      </canvas>
      <int name="price" value="20" />
      <int name="slotMax" value="1000" />
      <int name="incPAD" value="4" />
    </imgdir>
    <imgdir name="bullet">
      <canvas name="0" width="43" height="18">
        <vector name="origin" x="23" y="10" />
        <int name="z" value="0" />
      </canvas>
      <canvas name="1" width="41" height="9">
        <vector name="origin" x="22" y="5" />
        <int name="z" value="0" />
      </canvas>
    </imgdir>
  </imgdir>
  <imgdir name="02060005">
    <imgdir name="info">
      <canvas name="icon" width="26" height="25">
        <vector name="origin" x="-3" y="25" />
        <int name="z" value="0" />
      </canvas>
      <canvas name="iconRaw" width="20" height="18">
        <vector name="origin" x="-6" y="25" />
        <int name="z" value="0" />
      </canvas>
      <int name="slotMax" value="800" />
      <int name="incPAD" value="10" />
      <int name="reqLevel" value="10" />
      <int name="tradeBlock" value="1" />
    </imgdir>
    <imgdir name="bullet">
      <canvas name="0" width="36" height="19">
        <vector name="origin" x="22" y="9" />
        <int name="delay" value="150" />
      </canvas>
      <canvas name="1" width="40" height="22">
        <vector name="origin" x="20" y="11" />
        <int name="delay" value="150" />
      </canvas>
      <canvas name="2" width="43" height="21">
        <vector name="origin" x="21" y="10" />
        <int name="delay" value="150" />
      </canvas>
      <canvas name="3" width="46" height="23">
        <vector name="origin" x="20" y="11" />
        <int name="delay" value="150" />
      </canvas>
    </imgdir>
    <imgdir name="hit">
      <canvas name="0" width="55" height="38">
        <vector name="origin" x="13" y="20" />
        <int name="delay" value="90" />
      </canvas>
      <canvas name="1" width="43" height="55">
        <vector name="origin" x="17" y="29" />
        <int name="delay" value="100" />
      </canvas>
      <canvas name="2" width="51" height="65">
        <vector name="origin" x="26" y="34" />
        <int name="delay" value="100" />
      </canvas>
      <canvas name="3" width="62" height="87">
        <vector name="origin" x="34" y="57" />
        <int name="delay" value="100" />
      </canvas>
    </imgdir>
  </imgdir>

The catch is that there are many of these XML files, and each one has different header names, such as 0206.img, 0207.img. Each one has a very similar structure to the previous one in that header category (leading digit determines what type of object it is unmarshaling).

I really only want to reflect properties such as price, slotMax, incPad, and ignore the rest if possible. I'm not sure how to go about this, since in all the unmarshal examples the XML is much simpler, such as

<Employees>
    <Employee>
       <id>1</id>
    </Employee>
    <Employee>
      <id>2</id>
    </Employee>
</Employees>

Where you'd probably define a class like Employees which contains List, and Employee can be unmarshalled into. To clarify, I know you have to set the RootElement to the name of the top element, such as in this case 0206.img, but how can this be dynamic for 0207?

As for code ... I mean the code base is pretty simple since it's just defining the structure for which to unmarshal into. Defining this structure in respect to the above XML I linked is harder for me atm.

Jon Nguyen
  • 91
  • 1
  • 1
  • 8
  • https://stackoverflow.com/questions/686453/generate-java-classes-from-xsd-files – guleryuz May 09 '18 at 07:04
  • I'm not sure what you are talking about here? I'm already using JAXB in this particular case. – Jon Nguyen May 09 '18 at 07:12
  • I see the instructions on using it, but I still don't see how to get around the idea that I need it dynamic on already existent XML files. It seems like this person Marshalled first, which created the XML first. – Jon Nguyen May 09 '18 at 07:13
  • https://stackoverflow.com/questions/686453/generate-java-classes-from-xsd-files#15431812 – guleryuz May 09 '18 at 07:21
  • @guleryuz Before suggesting that you first need to make sure there's actually an XML Schema available. – lexicore May 09 '18 at 07:22

1 Answers1

0

If you're only interested in a few easy-to-detect elements, and not in the whole structure, JAXB may be a wrong tool. JAXB is good for the cases where you have an XML Schema, interested in (more or less) complete structure, unmarshalling as well as marshalling.

If you only need a few parts of XML there are easier ways to do this. In this particular case I would probably use STAX. Something along the lines:

private static final QName INT_ELEMENT_NAME = new QName("int");

// ...

    XMLInputFactory factory = XMLInputFactory.newInstance();
    XMLStreamReader reader = factory.createXMLStreamReader(is);

    while (reader.hasNext()) {
        if (XMLStreamConstants.START_ELEMENT == reader.next()) {
            if (Objects.equals(INT_ELEMENT_NAME, reader.getName())) {
                String name = reader.getAttributeValue(null, "name");
                String value = reader.getAttributeValue(null, "value");
                System.out.println(name + "=" + value);
            }
        }
    }

Prints name/value paits from all the int elements. Can be easily extended to further cases. Very fast, does not have the JAXB overhead, would easily work with big XML files, no matter how huge.

There are other tools as well. There was one parser (I could not recall the name) where you define XPath-based rules and the parser returns data according to these rules. That would also be suitable, but I just don't recall the name. I think it was some Apache project.

Update: I've finally found it, I was talking about Digester. It allows configuring XPath-like binding rules and the creates objects for you. Still, I'd probably stay with the STAX solution unless you're sure you'll get more and more complex rules.

lexicore
  • 42,748
  • 17
  • 132
  • 221
  • Interesting. Digester is looking pretty good. I'm curious though according to this post: https://stackoverflow.com/questions/34718226/digester-parser-error-java-lang-nosuchmethodexception-employee-init It can traverse tags, but as you can see in my document it has dynamic tags for each file such as 0206.img or 0207.img (depending which XML I'm reading). How do I dynamically bypass these? – Jon Nguyen May 09 '18 at 07:35
  • I don't see "dynamic" tags in the XML you've posted. What's "dynamic" anyway? – lexicore May 09 '18 at 07:39