Joe
Joe

Reputation: 13

Recursive XSLT generates text which doesn't match any template

Updating this post, to show where I'm currently at. So after some larification in my answer post, I'll update this post also with the current progress which is not so shiny. The XSLT stylesheet currently looks like the following:

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

    <xsl:template match="value" mode="values" />

    <xsl:template match="value[@name = 'field_name' or @name = 'field_type' or @name = 'field_dim']" mode="values">
        <xsl:element name="{@name}">
            <xsl:value-of select="text()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="record[ancestor::record[@name='sig_in' or @name='sig_out'] and value[@name = 'field_name']]">
        <xsl:param name="path" />

        <xsl:variable name ="newpath">
            <xsl:value-of select="concat($path,'/',  value[@name = 'field_name' ]/text())" />
        </xsl:variable>

        <xsl:copy>
            <xsl:attribute name="path">
                <xsl:value-of select="$newpath" />
            </xsl:attribute>

            <xsl:apply-templates mode="values" select="value" />

            <xsl:apply-templates>
                <xsl:with-param name="path" select="$newpath" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Input document from service xml signature:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Values version="2.0">
    <value name="svc_type">flow</value>
    <value name="svc_subtype">default</value>
    <value name="svc_sigtype">java 3.5</value>
    <record javaclass="com.wm.util.Values" name="svc_sig">
        <record javaclass="com.wm.util.Values" name="sig_in">
            <value name="node_type">record</value>
            <value name="is_public">false</value>
            <value name="field_type">record</value>
            <value name="field_dim">0</value>
            <value name="nillable">true</value>
            <value name="form_qualified">false</value>
            <value name="is_global">false</value>
            <array depth="1" name="rec_fields" type="record">
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">docTest</value>
                    <value name="field_type">record</value>
                    <value name="field_dim">0</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                    <array depth="1" name="rec_fields" type="record">
                        <record javaclass="com.wm.util.Values">
                            <value name="node_type">record</value>
                            <value name="node_comment"/>
                            <record javaclass="com.wm.util.Values" name="node_hints">
                                <null name="field_usereditable"/>
                                <value name="field_largerEditor">false</value>
                                <value name="field_password">false</value>
                            </record>
                            <value name="is_public">false</value>
                            <value name="field_name">doc.name</value>
                            <value name="field_type">string</value>
                            <value name="field_dim">0</value>
                            <value name="nillable">true</value>
                            <value name="form_qualified">false</value>
                            <value name="is_global">false</value>
                        </record>
                    </array>
                    <value name="rec_closed">true</value>
                    <value name="modifiable">true</value>
                </record>
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">docListTest</value>
                    <value name="field_type">record</value>
                    <value name="field_dim">1</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                    <value name="is_soap_array_encoding_used">false</value>
                    <array depth="1" name="rec_fields" type="record">
                        <record javaclass="com.wm.util.Values">
                            <value name="node_type">record</value>
                            <value name="node_comment"/>
                            <record javaclass="com.wm.util.Values" name="node_hints">
                                <value name="field_largerEditor">false</value>
                                <value name="field_password">false</value>
                            </record>
                            <value name="is_public">false</value>
                            <value name="field_name">d0</value>
                            <value name="field_type">record</value>
                            <value name="field_dim">0</value>
                            <value name="nillable">true</value>
                            <value name="form_qualified">false</value>
                            <value name="is_global">false</value>
                            <array depth="1" name="rec_fields" type="record">
                                <record javaclass="com.wm.util.Values">
                                    <value name="node_type">record</value>
                                    <value name="node_comment"/>
                                    <record javaclass="com.wm.util.Values" name="node_hints">
                                        <null name="field_usereditable"/>
                                        <value name="field_largerEditor">false</value>
                                        <value name="field_password">false</value>
                                    </record>
                                    <value name="is_public">false</value>
                                    <value name="field_name">d0.name</value>
                                    <value name="field_type">string</value>
                                    <value name="field_dim">0</value>
                                    <value name="nillable">true</value>
                                    <value name="form_qualified">false</value>
                                    <value name="is_global">false</value>
                                </record>
                            </array>
                            <value name="rec_closed">true</value>
                            <value name="modifiable">true</value>
                        </record>
                    </array>
                    <value name="rec_closed">true</value>
                    <value name="modifiable">true</value>
                </record>
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">packages_should_work</value>
                    <value name="field_type">recref</value>
                    <value name="field_dim">0</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                    <value name="rec_closed">true</value>
                    <value name="modifiable">true</value>
                    <value name="rec_ref">data:packages</value>
                </record>
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">packages_list_should_work</value>
                    <value name="field_type">recref</value>
                    <value name="field_dim">1</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                    <value name="is_soap_array_encoding_used">false</value>
                    <value name="rec_closed">true</value>
                    <value name="modifiable">true</value>
                    <value name="rec_ref">data:packages</value>
                </record>
            </array>
            <value name="modifiable">true</value>
        </record>
        <record javaclass="com.wm.util.Values" name="sig_out">
            <value name="node_type">record</value>
            <value name="is_public">false</value>
            <value name="field_type">record</value>
            <value name="field_dim">0</value>
            <value name="nillable">true</value>
            <value name="form_qualified">false</value>
            <value name="is_global">false</value>
            <array depth="1" name="rec_fields" type="record">
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <null name="field_usereditable"/>
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">doc</value>
                    <value name="field_type">string</value>
                    <value name="field_dim">0</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                </record>
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">lDoc</value>
                    <value name="field_type">string</value>
                    <value name="field_dim">1</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                    <value name="is_soap_array_encoding_used">false</value>
                </record>
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <null name="field_usereditable"/>
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">docR</value>
                    <value name="field_type">string</value>
                    <value name="field_dim">0</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                </record>
                <record javaclass="com.wm.util.Values">
                    <value name="node_type">record</value>
                    <value name="node_comment"/>
                    <record javaclass="com.wm.util.Values" name="node_hints">
                        <value name="field_largerEditor">false</value>
                        <value name="field_password">false</value>
                    </record>
                    <value name="is_public">false</value>
                    <value name="field_name">lDocR</value>
                    <value name="field_type">string</value>
                    <value name="field_dim">1</value>
                    <value name="nillable">true</value>
                    <value name="form_qualified">false</value>
                    <value name="is_global">false</value>
                    <value name="is_soap_array_encoding_used">false</value>
                </record>
            </array>
            <value name="modifiable">true</value>
        </record>
    </record>
    <value name="stateless">no</value>
    <value name="caching">no</value>
    <value name="prefetch">no</value>
    <value name="cache_ttl">15</value>
    <value name="prefetch_level">1</value>
    <value name="template">testfolder_documentTest</value>
    <value name="template_type">html</value>
    <value name="audit_level">off</value>
    <value name="check_internal_acls">no</value>
    <value name="icontext_policy">$null</value>
    <value name="system_service">no</value>
    <value name="retry_max">0</value>
    <value name="retry_interval">0</value>
    <value name="svc_in_validator_options">none</value>
    <value name="svc_out_validator_options">none</value>
    <value name="auditoption">0</value>
    <null name="auditfields_input"/>
    <null name="auditfields_output"/>
    <record javaclass="com.wm.util.Values" name="auditsettings">
        <value name="document_data">0</value>
        <value name="startExecution">false</value>
        <value name="stopExecution">false</value>
        <value name="onError">true</value>
    </record>
    <value name="pipeline_option">1</value>
    <null name="originURI"/>
    <value name="modifiable">true</value>
    <value name="is_public">false</value>
</Values>

Example xml after transformation (Desired format):

<?xml version="1.0" encoding="UTF-8"?>
<Values name = "svc_sig">
    <Inputs name = "sig_in">
        <record path = "sig_in/docTest">
            <field_name>docTest</field_name>
            <dield_type>record</dield_type>
            <field_dimension>value</field_dimension>
            <record path = "sig_in/docTest/doc.name">
                <field_name>doc.name</field_name>
                <field_type>string</field_type>
                <field_dimension>value</field_dimension>
            </record>
        </record>
        <record path = "sig_in/docListTest">
            <field_name>docListTest</field_name>
            <field_type>record</field_type>
            <field_dimension>array</field_dimension>
            <record path = "sig_in/docListTest/d0">
                <field_name>d0</field_name>
                <field_type>record</field_type>
                <field_dimension>value</field_dimension>
                <record path = "sig_in/docListTest/d0/d0.name">
                    <field_name>d0.name</field_name>
                    <field_type>string</field_type>
                    <field_dimension>value</field_dimension>
                </record>
            </record>
        </record>
        <record path = "sig_in/packages_should_work">
            <field_name>packages_should_work</field_name>
            <field_type>recref</field_type>
            <field_dimension>value</field_dimension>
            <record path = "sig_in/packages_should_work/data:packages" />
        </record>
        <record path = "sig_in/packages_list_should_work">
            <field_name>packages_list_should_work</field_name>
            <field_type>recref</field_type>
            <field_dimension>array</field_dimension>
            <record path = "sig_in/packages_list_should_work/data:packages" />
        </record>
    </Inputs>
    <Outputs name = "sig_out">
        <record path = "sig_out/doc">
            <field_name>doc</field_name>
            <field_type>string</field_type>
            <field_dimension>value</field_dimension>
        </record>
        <record path = "sig_out/lDoc">
            <field_name>lDoc</field_name>
            <field_type>string</field_type>
            <field_dimension>array</field_dimension>
        </record>
        <record path = "sig_out/docR">
            <field_name>docR</field_name>
            <field_type>string</field_type>
            <field_dimension>value</field_dimension>
        </record>
        <record path = "sig_out/lDocR">
            <field_name>lDocR</field_name>
            <field_type>string</field_type>
            <field_dimension>array</field_dimension>
        </record>
    </Outputs>
</Values>

What this stylesheet produces currently (Pretty far from the expected format...): Currently only trying to contain field_name nodes inside records and leave all others out.

<?xml version="1.0" encoding="UTF-8"?>
    flow
    default
    java 3.5


            record
            false
            record
            0
            true
            false
            false

                <record path="/docTest">
   <field_name>docTest</field_name>
   <field_type>record</field_type>
   <field_dim>0</field_dim>
                    record


                        false
                        false

                    false
                    docTest
                    record
                    0
                    true
                    false
                    false

                        <record path="/doc.name">
      <field_name>doc.name</field_name>
      <field_type>string</field_type>
      <field_dim>0</field_dim>
                            record



                                false
                                false

                            false
                            doc.name
                            string
                            0
                            true
                            false
                            false
                        </record>

                    true
                    true
                </record>

<record path="/docListTest">
   <field_name>docListTest</field_name>
   <field_type>record</field_type>
   <field_dim>1</field_dim>
                    record


                        false
                        false

                    false
                    docListTest
                    record
                    1
                    true
                    false
                    false
                    false

                        <record path="/d0">
      <field_name>d0</field_name>
      <field_type>record</field_type>
      <field_dim>0</field_dim>
                            record


                                false
                                false

                            false
                            d0
                            record
                            0
                            true
                            false
                            false

                                <record path="/d0.name">
         <field_name>d0.name</field_name>
         <field_type>string</field_type>
         <field_dim>0</field_dim>
                                    record



                                        false
                                        false

                                    false
                                    d0.name
                                    string
                                    0
                                    true
                                    false
                                    false
                                </record>

                            true
                            true
                        </record>

                    true
                    true
                </record>

<record path="/packages_should_work">
   <field_name>packages_should_work</field_name>
   <field_type>recref</field_type>
   <field_dim>0</field_dim>
                    record


                        false
                        false

                    false
                    packages_should_work
                    recref
                    0
                    true
                    false
                    false
                    true
                    true
                    data:packages
                </record>

<record path="/packages_list_should_work">
   <field_name>packages_list_should_work</field_name>
   <field_type>recref</field_type>
   <field_dim>1</field_dim>
                    record


                        false
                        false

                    false
                    packages_list_should_work
                    recref
                    1
                    true
                    false
                    false
                    false
                    true
                    true
                    data:packages
                </record>

            true


            record
            false
            record
            0
            true
            false
            false

                <record path="/doc">
   <field_name>doc</field_name>
   <field_type>string</field_type>
   <field_dim>0</field_dim>
                    record



                        false
                        false

                    false
                    doc
                    string
                    0
                    true
                    false
                    false
                </record>

<record path="/lDoc">
   <field_name>lDoc</field_name>
   <field_type>string</field_type>
   <field_dim>1</field_dim>
                    record


                        false
                        false

                    false
                    lDoc
                    string
                    1
                    true
                    false
                    false
                    false
                </record>

<record path="/docR">
   <field_name>docR</field_name>
   <field_type>string</field_type>
   <field_dim>0</field_dim>
                    record



                        false
                        false

                    false
                    docR
                    string
                    0
                    true
                    false
                    false
                </record>

<record path="/lDocR">
   <field_name>lDocR</field_name>
   <field_type>string</field_type>
   <field_dim>1</field_dim>
                    record


                        false
                        false

                    false
                    lDocR
                    string
                    1
                    true
                    false
                    false
                    false
                </record>

            true


    no
    no
    no
    15
    1
    testfolder_documentTest
    html
    off
    no
    $null
    no
    0
    0
    none
    none
    0



        0
        false
        false
        true

    1

    true
    false

The Transformer is set to Xalan. In JAVA if I try to run this transformer I get the following exception:

[Fatal Error] :2:3: Content is not allowed in prolog.

While the code that does the actual transformation is the following:

private static Document tme(Document o) throws Exception {
        StringWriter sw = new StringWriter();
        StreamSource s = new StreamSource(
                new StringReader("XSLT IN HERE as bare string copied from oxygen author"));
        Transformer transformer = TransformerFactory.newInstance().newTransformer(s);


        StreamResult res = new StreamResult(sw);
        transformer.transform(new DOMSource(o.getDocumentElement()), res);

        return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(sw.toString())));
    }

Upvotes: 1

Views: 178

Answers (2)

hr_117
hr_117

Reputation: 9627

Try something like this:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="value"  mode="values"/>

    <xsl:template match="value[@name = 'field_name' or
                            @name = 'field_type' or
                            @name = 'field_dim']" mode="values">
        <xsl:element name="{@name}">
            <xsl:value-of select="text()"/>
        </xsl:element>

    </xsl:template>

    <xsl:template match="record[ ancestor::record[@name='sig_in' or @name='sig_out'] and 
                             value[@name = 'field_name' ]]">
        <xsl:param name="path" />
        <xsl:variable name ="newpath">
            <xsl:value-of select="concat($path,'/',  value[@name = 'field_name' ]/text())" />
        </xsl:variable>
        <xsl:copy>
            <xsl:attribute name="path">
                <xsl:value-of select="$newpath"/>
            </xsl:attribute>
            <xsl:apply-templates  mode="values" select="value"/>
            <xsl:apply-templates  >
                <xsl:with-param name="path" select="$newpath" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>



    <xsl:template match="record[@name='sig_in']" >
        <Inputs name="sig_in" >
            <xsl:apply-templates  >
                <xsl:with-param name="path" select="'sig_in'" />
            </xsl:apply-templates>
        </Inputs>
    </xsl:template>

    <xsl:template match="record[@name='sig_out']" >
        <Outputs name = "sig_out">
            <xsl:apply-templates  >
                <xsl:with-param name="path" select="'sig_out'" />
            </xsl:apply-templates>
        </Outputs>
    </xsl:template>

    <xsl:template match="Values[descendant::record[@name='svc_sig'] ]">
        <Values name="svc_sig">
            <xsl:apply-templates  select="descendant::record[@name='svc_sig']"/>
        </Values>
    </xsl:template>

    <xsl:template match="node()">
        <xsl:param name="path" />
        <xsl:apply-templates  select="node()" >
            <xsl:with-param name="path" select="$path" />
        </xsl:apply-templates>

    </xsl:template>

</xsl:stylesheet>

Which will generate following output:

<?xml version="1.0"?>
<Values name="svc_sig">
  <Inputs name="sig_in">
    <record path="sig_in/docTest">
      <field_name>docTest</field_name>
      <field_type>record</field_type>
      <field_dim>0</field_dim>
      <record path="sig_in/docTest/doc.name">
        <field_name>doc.name</field_name>
        <field_type>string</field_type>
        <field_dim>0</field_dim>
      </record>
    </record>
    <record path="sig_in/docListTest">
      <field_name>docListTest</field_name>
      <field_type>record</field_type>
      <field_dim>1</field_dim>
      <record path="sig_in/docListTest/d0">
        <field_name>d0</field_name>
        <field_type>record</field_type>
        <field_dim>0</field_dim>
        <record path="sig_in/docListTest/d0/d0.name">
          <field_name>d0.name</field_name>
          <field_type>string</field_type>
          <field_dim>0</field_dim>
        </record>
      </record>
    </record>
    <record path="sig_in/packages_should_work">
      <field_name>packages_should_work</field_name>
      <field_type>recref</field_type>
      <field_dim>0</field_dim>
    </record>
    <record path="sig_in/packages_list_should_work">
      <field_name>packages_list_should_work</field_name>
      <field_type>recref</field_type>
      <field_dim>1</field_dim>
    </record>
  </Inputs>
  <Outputs name="sig_out">
    <record path="sig_out/doc">
      <field_name>doc</field_name>
      <field_type>string</field_type>
      <field_dim>0</field_dim>
    </record>
    <record path="sig_out/lDoc">
      <field_name>lDoc</field_name>
      <field_type>string</field_type>
      <field_dim>1</field_dim>
    </record>
    <record path="sig_out/docR">
      <field_name>docR</field_name>
      <field_type>string</field_type>
      <field_dim>0</field_dim>
    </record>
    <record path="sig_out/lDocR">
      <field_name>lDocR</field_name>
      <field_type>string</field_type>
      <field_dim>1</field_dim>
    </record>
  </Outputs>
</Values>

Attention: here are still two differences to your expected output (I did not find reasonable info how to build them):
* There is no field_dimension in output.
* Tow records are missing
<record path = "sig_in/packages_list_should_work/data:packages" />

Upvotes: 1

LarsH
LarsH

Reputation: 28004

It's not easy to tell if this is addressing the problem that you're describing, but in the middle of the above XSLT fragment,

<xsl:attribute name="name">
  <xsl:value-of
    select="concat($parent_node, '/', self::node[@name]/@name)" />
</xsl:attribute>

you could try changing the select attribute to:

    select="concat($parent_node, '/', data)" />

That seems too obvious, so maybe I'm missing something.

Upvotes: 0

Related Questions