1

I've compiled an XSL document to transform custom XML documents to GraphML (with some additional metadata for the yEd Graph Editor). The transformation works as expected and completes, but there's one problem. No matter which tool I've used to perform the transformation, the resulting document is comprised of a single line, so I have to format it every time I perform a transformation. My question is:

How can I adjust my XSL document to have a pretty-printed XML document?

OR

What am I doing wrong?

My XSL code is the following:

<xsl:stylesheet version="1.0" encoding="UTF-8" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/paths">
        <graphml xmlns="http://graphml.graphdrawing.org/xmlns"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:y="http://www.yworks.com/xml/graphml"
 xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd">
            <key id="workerDescription" for="node" yfiles.type="nodegraphics"/>
            <key for="edge" id="response" yfiles.type="edgegraphics"/>
            <xsl:for-each select="path">
                <graph edgedefault="directed">
                    <xsl:attribute name="id">
                        <xsl:value-of select="@id"/>
                    </xsl:attribute>

                    <node>
                        <xsl:attribute name="id">
                            <xsl:value-of select="@id"/>
                        </xsl:attribute>
                        <data key="workerDescription">
                            <y:ShapeNode>
                                <y:Fill color="#FFCC00" transparent="false"/>
                                <y:NodeLabel>
                                    <xsl:value-of select="@id"/>
                                </y:NodeLabel>
                            </y:ShapeNode>
                        </data>
                    </node>

                    <xsl:for-each select="entry-point">
                        <edge>
                            <xsl:attribute name="source">
                                <xsl:value-of select="../@id"></xsl:value-of>
                            </xsl:attribute>
                            <xsl:attribute name="target">
                                <xsl:value-of select="../@id"/>.<xsl:value-of select="@worker-ref"/>
                            </xsl:attribute>
                        </edge>
                    </xsl:for-each>

                    <xsl:for-each select="worker">
                        <node>
                            <xsl:attribute name="id">
                                <xsl:value-of select="../@id"/>.<xsl:value-of select="@id"/>
                            </xsl:attribute>
                            <data key="workerDescription">
                                <y:ShapeNode>
                                    <xsl:attribute name="alignment">center</xsl:attribute>
                                    <xsl:attribute name="autoSizePolicy">content</xsl:attribute>
                                    <xsl:attribute name="modelName">internal</xsl:attribute>
                                    <xsl:attribute name="modelPosition">c</xsl:attribute>
                                    <y:NodeLabel>
                                        <xsl:choose>
                                            <xsl:when test="@idref = 'CallPath'">
                                                <xsl:value-of select="@id"/> &gt; <xsl:value-of select="context/value/map/entry/@value"/>
                                            </xsl:when>
                                            <xsl:otherwise>
                                                <xsl:value-of select="@id"/> &gt; <xsl:value-of select="@idref"/>
                                            </xsl:otherwise>
                                        </xsl:choose>
                                    </y:NodeLabel>
                                    <xsl:if test="@idref = 'CallPath'">
                                        <y:Fill color="#FFCC00" transparent="false"/>
                                    </xsl:if>
                                </y:ShapeNode>
                            </data>
                        </node>

                        <xsl:for-each select="response">
                            <edge>
                                <xsl:attribute name="source">
                                    <xsl:value-of select="../../@id"/>.<xsl:value-of select="../@id"/>
                                </xsl:attribute>
                                <xsl:attribute name="target">
                                    <xsl:value-of select="../../@id"/>.<xsl:value-of select="@worker-ref | @exit"/>
                                </xsl:attribute>
                                <xsl:attribute name="directed">true</xsl:attribute>
                                <data key="response">
                                    <y:PolyLineEdge>
                                        <y:EdgeLabel>
                                            <xsl:value-of select="@name"/>
                                        </y:EdgeLabel>
                                        <y:Arrows source="none" target="standard"/>
                                    </y:PolyLineEdge>
                                </data>
                            </edge>

                            <xsl:for-each select="@exit">
                                <node>
                                    <xsl:attribute name="id">
                                        <xsl:value-of select="../../../@id"/>.<xsl:value-of select="."/>
                                    </xsl:attribute>
                                    <data key="workerDescription" transparent="false">
                                        <y:ShapeNode>
                                            <xsl:attribute name="alignment">center</xsl:attribute>
                                            <xsl:attribute name="autoSizePolicy">content</xsl:attribute>
                                            <xsl:attribute name="modelName">internal</xsl:attribute>
                                            <xsl:attribute name="modelPosition">c</xsl:attribute>
                                            <y:Fill color="#FF0000"/>
                                            <y:NodeLabel>
                                                <xsl:value-of select="."/>
                                            </y:NodeLabel>
                                        </y:ShapeNode>
                                    </data>
                                </node>
                            </xsl:for-each>
                        </xsl:for-each>
                    </xsl:for-each>
                </graph>
            </xsl:for-each>
        </graphml>
    </xsl:template>
</xsl:stylesheet>

My input is the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE paths SYSTEM "paths.dtd">
<paths>
    <path id="PathID">
        <entry-point name="start" worker-ref="EntryWorker" />
        <worker id="EntryWorker" idref="EntryWorkerClass">
            <response name="SUCCESS" worker-ref="MarkScoring" />
            <response name="ERROR" exit="ERRORM" />
        </worker>
        <worker id="MarkScoring" idref="MarkScoringClass">
            <response name="SUCCESS" exit="SUCCESS" />
            <response name="ERROR" exit="ERRORSCOR" />
        </worker>
    </path>
</paths>

And my output is the following:

<?xml version="1.0"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd">
    <key id="workerDescription" for="node" yfiles.type="nodegraphics"/>
    <key for="edge" id="response" yfiles.type="edgegraphics"/>
    <graph edgedefault="directed" id="PathID">
        <node id="PathID">
            <data key="workerDescription">
                <y:ShapeNode>
                    <y:Fill color="#FFCC00" transparent="false"/>
                    <y:NodeLabel>PathID</y:NodeLabel>
                </y:ShapeNode>
            </data>
        </node>
        <edge source="PathID" target="PathID.EntryWorker"/>
        <node id="PathID.EntryWorker">
            <data key="workerDescription">
                <y:ShapeNode alignment="center" autoSizePolicy="content" modelName="internal" modelPosition="c">
                    <y:NodeLabel>EntryWorker &gt; EntryWorkerClass</y:NodeLabel>
                </y:ShapeNode>
            </data>
        </node>
        <edge source="PathID.EntryWorker" target="PathID.MarkScoring" directed="true">
            <data key="response">
                <y:PolyLineEdge>
                    <y:EdgeLabel>SUCCESS</y:EdgeLabel>
                    <y:Arrows source="none" target="standard"/>
                </y:PolyLineEdge>
            </data>
        </edge>
        <edge source="PathID.EntryWorker" target="PathID.ERRORM" directed="true">
            <data key="response">
                <y:PolyLineEdge>
                    <y:EdgeLabel>ERROR</y:EdgeLabel>
                    <y:Arrows source="none" target="standard"/>
                </y:PolyLineEdge>
            </data>
        </edge>
        <node id="PathID.ERRORM">
            <data key="workerDescription" transparent="false">
                <y:ShapeNode alignment="center" autoSizePolicy="content" modelName="internal" modelPosition="c">
                    <y:Fill color="#FF0000"/>
                    <y:NodeLabel>ERRORM</y:NodeLabel>
                </y:ShapeNode>
            </data>
        </node>
        <node id="PathID.MarkScoring">
            <data key="workerDescription">
                <y:ShapeNode alignment="center" autoSizePolicy="content" modelName="internal" modelPosition="c">
                    <y:NodeLabel>MarkScoring &gt; MarkScoringClass</y:NodeLabel>
                </y:ShapeNode>
            </data>
        </node>
        <edge source="PathID.MarkScoring" target="PathID.SUCCESS" directed="true">
            <data key="response">
                <y:PolyLineEdge>
                    <y:EdgeLabel>SUCCESS</y:EdgeLabel>
                    <y:Arrows source="none" target="standard"/>
                </y:PolyLineEdge>
            </data>
        </edge>
        <node id="PathID.SUCCESS">
            <data key="workerDescription" transparent="false">
                <y:ShapeNode alignment="center" autoSizePolicy="content" modelName="internal" modelPosition="c">
                    <y:Fill color="#FF0000"/>
                    <y:NodeLabel>SUCCESS</y:NodeLabel>
                </y:ShapeNode>
            </data>
        </node>
        <edge source="PathID.MarkScoring" target="PathID.ERRORSCOR" directed="true">
            <data key="response">
                <y:PolyLineEdge>
                    <y:EdgeLabel>ERROR</y:EdgeLabel>
                    <y:Arrows source="none" target="standard"/>
                </y:PolyLineEdge>
            </data>
        </edge>
        <node id="PathID.ERRORSCOR">
            <data key="workerDescription" transparent="false">
                <y:ShapeNode alignment="center" autoSizePolicy="content" modelName="internal" modelPosition="c">
                    <y:Fill color="#FF0000"/>
                    <y:NodeLabel>ERRORSCOR</y:NodeLabel>
                </y:ShapeNode>
            </data>
        </node>
    </graph>
</graphml>

I'm using Notepad++ "XML Tools" plugin to transform and format my documents. Any suggestion to incorporate an XSLT transformation with formatted end results to my workflow (programmatically or otherwise) is welcome.

2 Answers2

0

Try <xsl:method output="xml" indent="yes"/> between the xsl:stylesheet and the xsl:template. For some processors it might work.

(But what is your problem with a non-indented XML?)

Stefan Hegny
  • 2,107
  • 4
  • 23
  • 26
  • I tried your suggestion, but it didn't work. The transformation fails. :-( I need to compile a set of XML documents to GraphML, and I need them to be available for adjustments by hand, because the resulting GraphML is not always a valid graph. – Puzzled Solver Sep 25 '16 at 21:24
  • @PuzzledSolver "*it didn't work*" is a useless description, and so is "*the transformation fails*". Describe what did not work. If you received an error, quote it verbatim. Also let us know which processor are you using. – michael.hor257k Sep 25 '16 at 22:36
  • @michael.hor257k I'm using Notepad++ "XML Tools" plugin to transform my documents. The thrown error is "Unable to apply transformation on current source. Error occurred in source parsing. Make sure that XSL is valid." – Puzzled Solver Sep 26 '16 at 14:14
0

Change this part:

<xsl:stylesheet version="1.0" encoding="UTF-8" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

to:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51