1

I'm working on XSLT for an XML file that has a bunch of values for a particular "ID". I need to run this through my converter, which outputs those values to a database, but all I have to identify the values is the ID. What I need to identify the values is the description which is in another file. This description should become the output XML's element name, rather than the ID, which is what I'm using now. The same counter IDs are in the separate file and contain the description I need to use as the element name. Here is an example, just in case I'm confusing you.

<!-- XML with values -->
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
    <series>
        <sampleInfo>
            <timestamp>1/1/2013 12:00 AM</timestamp>
            <timestamp>1/2/2013 12:00 AM</timestamp>
            <timestamp>1/3/2013 12:00 AM</timestamp>
            <timestamp>1/4/2013 12:00 AM</timestamp>
        </sampleInfo>
        <value>
            <series>
                <value>
                    <int>0</int>
                    <int>9</int>
                    <int>0</int>
                    <int>9</int>
                </value>
                <id>
                    <counterID>100</counterID>
                    .
                    .
                </id>
            </series>
            <series>
                <value>
                    <int>3</int>
                    <int>6</int>
                    <int>3</int>
                    <int>6</int>
                </value>
                <id>
                    <counterID>120</counterID>
                    .
                    .
                    .
                </id>
            </series>
        </value>
    </series>
</root>

Basically, each timestamp has its own value for each of the corresponding counterIDs. Now here is a sample of the other XML file, the one I'm grabbing information from.

<!-- XML with descriptions -->
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
    <counterInfo>
        <id>100</id>
        <description>Blah</description>
    </counterInfo>
    <counterInfo>
        <id>120</id>
        <description>Derp</description>
    </counterInfo>
</root>

So once I convert the original document (the one with the values), my output (flat) XML looks sorta like:

<root>
    <element>
        <timestamp>1/1/2013 12:00 AM</timestamp>
        <C100>0</C100> <!-- Since XML doesn't allow numeric element fields, I add a C -->
        <C120>3</C120>
    </element>
    <element>
        <timestamp>1/2/2013 12:00 AM</timestamp>
        <C100>9</C100>
        <C120>6</C120>
    </element>
    <element>
        <timestamp>1/3/2013 12:00 AM</timestamp>
        <C100>0</C100>
        <C120>3</C120>
    </element>
    <element>
        <timestamp>1/4/2013 12:00 AM</timestamp>
        <C100>9</C100>
        <C120>6</C120>
    </element>
</root>

What I then need to do is transform the already flat XML, like above, to show this instead.

<root>
    <element>
        <timestamp>1/1/2013 12:00 AM</timestamp>
        <Blah>0</Blah>
        <Derp>3</Derp>
    </element>
    <element>
        <timestamp>1/2/2013 12:00 AM</timestamp>
        <Blah>9</Blah>
        <Derp>6</Derp>
    </element>
    <element>
        <timestamp>1/3/2013 12:00 AM</timestamp>
        <Blah>0</Blah>
        <Derp>3</Derp>
    </element>
    <element>
        <timestamp>1/4/2013 12:00 AM</timestamp>
        <Blah>9</Blah>
        <Derp>6</Derp>
    </element>
</root>

I did a bit of searching, and most results suggest parameters, but the way I convert these may make this a little difficult. I have a converter in Java that's part of a large repository of converters, and it pulls the XSLT from that repository to transform files passed to it. In the converter, we extract files that need to be converted from archives and then do them each individually. So my problem is... how do I give the XSLT that filename when the converter gets to that file in the list, and how do I pass that filename to the XSLT?

So am I over-complicating things? Is there any easy way of accomplishing this? Let me know if I need to clear anything up.

Darin Beaudreau
  • 375
  • 7
  • 30
  • Where is the XSLT that you have so far? To pass a filename into the XSLT, you would use an XSLT parameter, and then you could pass this parameter to the `document()` function to access the file's contents. [This answer](http://stackoverflow.com/questions/1667454/xsl-transformation-in-java-with-parameters) shows how to use XSLT parameters in Java. – JLRishe Mar 05 '13 at 18:21
  • The XSLT is in one of the projects in Eclipse, which is taken from an SVN repository. When the converter is run, the init() function gets it the proper converter for each specific file, and then runs those converters. The converters take the XSLT stylesheet and run it against the files assigned to it. The files themselves are taken from an archive (7z, zip, etc), converted (flattened), then turned into CSV files and re-archived. The files don't have an actual location, and are stored as File objects when the converter runs... so you see my dilemma? – Darin Beaudreau Mar 05 '13 at 21:43

1 Answers1

1

Opening a document is very easy, and can be parameterized. BUT creating an element name that is 'C' concat some number (eg, 'C100') is a terrible, terrible, terrible idea. Why? Because it would be very difficult (in xsl) to find those nodes; also, 'C100' 'C125' nodes would blow away any attempt to create a schema.

Instead of creating your own element, use an attribute: <descr id="100">0</descr>.

Input XML (file.xml)

Okay, so, here is an xml using the descr element instead:

<root>
    <element>
        <timestamp>1/1/2013 12:00 AM</timestamp>
        <descr id="100">0</descr>
        <descr id="120">3</descr>
    </element>
    <element>
        <timestamp>1/2/2013 12:00 AM</timestamp>
        <descr id="100">9</descr>
        <descr id="120">6</descr>
    </element>
    <element>
        <timestamp>1/3/2013 12:00 AM</timestamp>
        <descr id="100">0</descr>
        <descr id="120">3</descr>
    </element>
    <element>
        <timestamp>1/4/2013 12:00 AM</timestamp>
        <descr id="100">9</descr>
        <descr id="120">6</descr>
    </element>
</root>

Description XML (descriptions.xml)

<root>
    <counterInfo>
        <id>100</id>
        <description>Blah</description>
    </counterInfo>
    <counterInfo>
        <id>120</id>
        <description>Derp</description>
    </counterInfo>
</root>

XSL

And finally, the style sheet to merge them:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:param name="descrDoc" select="'descriptions.xml'" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="descr">
      <xsl:variable name="nodeName">
        <xsl:value-of select="document($descrDoc)/*/counterInfo[ id = current()/@id ]/description" />
      </xsl:variable>
      <xsl:if test="string-length($nodeName)=0">
        <xsl:message terminate="yes">No description! Failed.</xsl:message>
      </xsl:if>
      <xsl:element name="{$nodeName}">
        <xsl:apply-templates />
      </xsl:element>
    </xsl:template>

</xsl:stylesheet>
Community
  • 1
  • 1
ljdelight
  • 486
  • 4
  • 13
  • I don't think you're understanding me. The format of the output XML isn't the problem. The file containing the raw XML which is converted to the flat format is taken from an archive, turned into a File object in Java, and then converted using an XsltConverter class we have. Then it is turned into a CSV and re-archived. In other words, the XML file I am trying to style, as well as the XML file with the descriptions I need to merge with it via XSLT, are File objects, and therefore, cannot simply have their filenames passed as parameters. – Darin Beaudreau Mar 05 '13 at 21:39
  • And I know "C100" etc is a bad idea... which is why I'm trying to take the descriptions from the other file and use THOSE as the element names, rather than "C100" etc. – Darin Beaudreau Mar 05 '13 at 21:39
  • Oh. So you only need to know to tell your transformer about a parameter? Java transformer setParameter: http://docs.oracle.com/javase/6/docs/api/javax/xml/transform/Transformer.html – ljdelight Mar 05 '13 at 22:27
  • Then you can fix the 'C100' stuff with a couple of regex: s/ – ljdelight Mar 05 '13 at 22:39
  • I know how to SET a parameter... but the problem is my parameter is a File object... I don't have an actual location on the disk for it. – Darin Beaudreau Mar 06 '13 at 14:23
  • Alright I understand. Try this: http://stackoverflow.com/questions/8887537/pass-document-as-parameter-to-xsl-translation-in-java – ljdelight Mar 06 '13 at 17:48