0
votes

I'd like to transform some xml files using xslt, but encountered a big problem.

In my input files i have CDATA tags, which contain xml subtree-s, and should be copied to the output tag. We know some informations about these CDATA tags:

They have a specific name: SUBXML1, SUBXML2, SUBXML3, and so on and so forth. Their content is fixed: some of there SUBXMLn-s contain only one element (<a>...</a>), some of them contain a list of elements (<a>...</a><a>...</a>), or multiple and/or list of elements (<a>...</a><b>...</b><b>...</b>).

I would like to transform them using IBM Message Broker (xsl transform node, we use it for like a hundred types messages, but didn't have this problem so far). We have a strict rule for these transformations: we can't use anything else, we have to achieve out goal with XLS; we can use only xslt 1.0 (broker doesn't support 2.0 or 3.0); we can't change the structure of the input/output messages (lots of systems use the defined structures so we can't touch them).

So here's the thing:

I have an input XML document:

<ns1:myOperation xmlns:ns1="http://mynamespace/">
    <SUBXML1>
        <![CDATA[<metaData><value>value1</value></metaData><metaData><value>value2</value></metaData><notMetaData><notValue>value3</notValue></notMetaData>]]>
    </SUBXML1>
</ns1:myOperation>

And i have my xsl like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://mynamespace/">
    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" omit-xml-declaration="yes" />

    <xsl:template match="/">
        <xsl:apply-templates select="ns1:myOperation" />
    </xsl:template>

    <xsl:template match="ns1:myOperation">
        <ns1:myOperation>
            <xsl:apply-templates select="SUBXML1" />
        </ns1:myOperation>
    </xsl:template>

    <xsl:template match="SUBXML1">
        <xsl:element name="one">
            <xsl:element name="metaData">
                <xsl:value-of
                    select="substring-before(substring-after(.,'metaData&gt;'), '&lt;/metaData')" disable-output-escaping="yes" />
            </xsl:element>
        </xsl:element>
        <xsl:element name="all">
            <xsl:element name="allSUBXML1">
                <xsl:value-of
                    select="." disable-output-escaping="yes" />
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

The output of this will be:

<ns1:myOperation xmlns:ns1="http://mynamespace/">
    <one>
        <metaData>
            <value>value1</value>
        </metaData>
    </one>
    <all>
        <allSUBXML1 />
    </all>
</ns1:myOperation>

Note: if you're testing this example in eclipse it will work (the <allSUBXML1> wont be empty), BUT xsl:value-of select should work only in elements! Thus in message broker it will generate an emtpy <allSUBXML1 /> element, but in eclipse somehow (a bug maybe?) it'll generate a "full output" so, it'll populate that field with the SUBXML1 content.

Back to my issue: the transformed xml has nothing in the <allSUBXML1 /> node, because i have no elements (only a big text) under <SUBXML1>...</SUBXML1> in my input xml.

How can i achieve my goal (to copy everything from SUBXML1 to my output's desired element)?

I can't use value-of select, because there are no elements under SUBXML1, only a big string. I can't use copy-of, because if won't convert the CDATA properly (i don't want to see "&lt;" and "&gt;" in my output, it should be a valid XML subtree).

As you can see i've tried to do some tricks using substring-before(substrin-after(.,...), ...) to get one inner element from SUBXML1, and it works, but that's not enough.

Is there any tricky way to copy everything from <SUBXML1> to <allSUBXML1> (so all inner elements)?

Thanks in forward, Tamas

1
I don't understand your question. You say your goal is "to copy everything from SUBXML1 to my output's desired element". If you really want to copy everything (as opposed to extracting only portions of the pseudo-XML), then what's wrong with using <xsl:value-of>, with disable-output-escaping set to "yes"? - michael.hor257k
My question is: Is there any tricky way to copy the content under SUBXML1 to the output's allSUBXML1? what's wrong with using <xsl:value-of>, with disable-output-escaping set to "yes"?: it's not working. The xslt processor under IMB Message Broker generates and empty element: <allSUBXML1 /> (however in eclipse it's working). That why i can't use value-of. It's not working :( - amman
I don't know of another way, using XSLT. If it doesn't work in your environment, then you're not using XSLT. So perhaps you need to use something else. - michael.hor257k
Possible duplicate of XSLT parse text node as XML? - nwellnhof

1 Answers

0
votes

Are you dead set on using XSLT? You could use the parse as bitstream clause in ESQL to do this pretty easily I would think.