如何使用 saxonica 将 xml 转换为 graphviz

Posted

技术标签:

【中文标题】如何使用 saxonica 将 xml 转换为 graphviz【英文标题】:How to convert xml to graphviz using saxonica 【发布时间】:2021-12-30 06:59:14 【问题描述】:

我有一个xml代码如下图,xml包含几个元素,分别是:id、父菜单、标签、角色id、角色和项目。 items中有1个元素,即子菜单,子菜单中有2个元素,即url和label:

    <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type = "text/xsl" href = "policy.xsl" ?>
<Import>
    <Row>
        <id>1</id>
        <parentmenu>siasn-instansi</parentmenu>
        <label>Layanan Profile ASN</label>
        <role_id>1</role_id>
        <role>role:siasn-instansi:profilasn:viewprofil</role>
        <items>
            <subMenu name = "pns">
                 <url>/tampilanData/pns</url>
                 <label>Profile Pegawai</label>
            </subMenu>
            <subMenu name = "pppk">
                 <url>/tampilanData/pppk</url>
                 <label>Profile Pegawai PPPK</label>
            </subMenu>
            <subMenu name = "ppt">
                 <url>/tampilanData/JPTNonASN</url>
                 <label>Profile Pegawai PPT Non-ASN</label>
            </subMenu>
        </items>
    </Row>
</Import>

下面的代码是xslt的代码,使用XSL语言和dotML。

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.martin-loetzsch.de/DOTML" version="3.0">
    <xsl:import href="http://www.martin-loetzsch.de/DOTML/dotml2dot.xsl"/>
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:variable name="dotml">
          <xsl:for-each select = "Import/Row">
            <graph file-name="graphs/node">
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                </node>   
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='items/subMenu[@name="pns"]/url'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='items/subMenu[@name="pns"]/url'/>
                    </xsl:attribute>
                </node>   
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='items/subMenu[@name="pppk"]/url'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='items/subMenu[@name="pppk"]/url'/>
                    </xsl:attribute>
                </node>   
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='items/subMenu[@name="ppt"]/url'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='items/subMenu[@name="ppt"]/url'/>
                    </xsl:attribute>
                </node>  

                <edge fontname="Arial" fontsize="9" label="Permit">
                    <xsl:attribute name="from">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="to">
                        <xsl:value-of select='items/subMenu[@name="pns"]/url'/>
                    </xsl:attribute>
                </edge>   
                <edge fontname="Arial" fontsize="9" label="Permit">
                    <xsl:attribute name="from">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="to">
                        <xsl:value-of select='items/subMenu[@name="pppk"]/url'/>
                    </xsl:attribute>
                </edge>   
                <edge fontname="Arial" fontsize="9" label="Permit">
                    <xsl:attribute name="from">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="to">
                        <xsl:value-of select='items/subMenu[@name="ppt"]/url'/>
                    </xsl:attribute>
                </edge>   
            </graph>
          </xsl:for-each>         
        </xsl:variable>
        <xsl:apply-templates select="$dotml/node()"/>
      
    </xsl:template>    
</xsl:stylesheet>

上面的xsl是我的xml文档的xslt。我想转换它以便它可以在graphviz上运行。我已经根据@martin Honnen 的建议更正了上面的代码,添加了代码:

<xsl:import href="http://www.martin-loetzsch.de/DOTML/dotml2dot.xsl"/>
<xsl:output method="text"/>
<xsl:apply-templates select="$dotml/node()"/>

并已成功从 dotML 代码更改为 graphviz 代码,如下面的代码:

    digraph g 
    compound="true";bgcolor="";fontcolor="";fontname="";fontsize="";label="";margin="";nodesep="";rankdir="";ranksep="";ratio="";size="";
    node[label="role:siasn-instansi:profilasn:viewprofil", color="",fillcolor="",fixedsize="",fontcolor="",fontname="",fontsize="16",,shape="",style="filled",URL="",,] 
         role:siasn-instansi:profilasn:viewprofil;
         node[label="/tampilanData/pns", color="",fillcolor="",fixedsize="",fontcolor="",fontname="",fontsize="16",,shape="",style="filled",URL="",,] 
         /tampilanData/pns;
         node[label="/tampilanData/pppk", color="",fillcolor="",fixedsize="",fontcolor="",fontname="",fontsize="16",,shape="",style="filled",URL="",,] 
         /tampilanData/pppk;
         node[label="/tampilanData/JPTNonASN", color="",fillcolor="",fixedsize="",fontcolor="",fontname="",fontsize="16",,shape="",style="filled",URL="",,] 
        /tampilanData/JPTNonASN;
        edge[arrowhead="",arrowsize="",arrowtail="",constraint="",color="",decorate="",dir="",fontcolor="",fontname="Arial",fontsize="9",headlabel="",headport="",label="Permit",labeldistance="",labelfloat="",labelfontcolor="",labelfontname="",labelfontsize="",minlen="",samehead="",sametail="",style="",taillabel="",tailport="",URL="",lhead="",ltail=""]
         role:siasn-instansi:profilasn:viewprofil -> /tampilanData/pns;edge[arrowhead="",arrowsize="",arrowtail="",constraint="",color="",decorate="",dir="",fontcolor="",fontname="Arial",fontsize="9",headlabel="",headport="",label="Permit",labeldistance="",labelfloat="",labelfontcolor="",labelfontname="",labelfontsize="",minlen="",samehead="",sametail="",style="",taillabel="",tailport="",URL="",lhead="",ltail=""] 
         role:siasn-instansi:profilasn:viewprofil -> /tampilanData/pppk;edge[arrowhead="",arrowsize="",arrowtail="",constraint="",color="",decorate="",dir="",fontcolor="",fontname="Arial",fontsize="9",headlabel="",headport="",label="Permit",labeldistance="",labelfloat="",labelfontcolor="",labelfontname="",labelfontsize="",minlen="",samehead="",sametail="",style="",taillabel="",tailport="",URL="",lhead="",ltail=""] 
         role:siasn-instansi:profilasn:viewprofil -> /tampilanData/JPTNonASN;
    
<dot-filename>graphs/node</dot-filename>

上面的代码是我使用 saxonica 进行的转换的结果,如下面的代码:

java -jar saxon-he-10.6.jar role-policy.xml role-policy.xsl -o:policy.txt

我想知道我使用 xsl 文档从 xml 转换的代码的内容是如何在 saxonica 的帮助下制作成 txt 格式的,就像上面的代码一样。

然后根据我的目标的最后一步,我立即将我的xml文件转换为点文件,使用saxonica以及下面的代码:

C:\Users\rafif\Desktop\saxons>dot -Tpng policy.dot -o policy_dot.png
Error: policy.dot: syntax error in line 1 near '-'

但不幸的是它仍然是一个错误。

问题仅出现在我的 xml 文档中每个提取值的“双引号”中。

还有第二个问题,使用saxon转换时,还是有&lt;dot-filename&gt;graphs/node&lt;/dot-filename&gt;标签,

问题是,如何在我的 xsl 文档中获取此标记:&lt;xsl:value-of select='items/subMenu[@name="pns"]/url'/&gt;&lt;xsl:value-of select='role'/&gt; 标记,当使用 saxon 转换为点文件时,结果将变为值中的字符串(有双引号)。

以及如何去除&lt;dot-filename&gt;graphs/node&lt;/dot-filename&gt;标签?

所以我不需要先转换成txt文件,每个值加上“双引号”,去掉&lt;dot-filename&gt;graphs/node&lt;/dot-filename&gt;标签,这样文件就可以直接转换成点了。不用先转成txt

谢谢

【问题讨论】:

正如 Martin 所说,您需要将 dotML 转换为 dot 语法。另请注意,您的代码不需要如此冗长,例如第 6..13 行可以替换为&lt;node style="filled" fontsize="16" id="role" label="role" /&gt;。 (查找“属性值模板”)。 michael 谢谢你的回复,你能看到我上面的问题吗,因为我的问题已经更新了,你能帮帮我吗?谢谢 这不是答案,只是一些注释:您在问题中显示的输出不是有效的 DOT 文件。要将其转换为有效的内容,您可以采取以下步骤: (1) 删除包含 ... ; 的行(如果这些是 DOT 语法的一部分,我不熟悉它们)。 (2) 确保您的边缘标签都包含在双引号中 - 因此,从 abc -&gt; def 到 "abc" -> "def"`。如果您进行这些更改,那么您将能够生成一个有效的 PNG 文件。它会是你真正想要的PNG吗?我不知道。您如何更改您的 XML 处理代码来实现这一点?我不知道。 我做到了....我爱你,andrewwww ... !!!! @andrewJames 你能看到我上面的问题吗,因为我的问题已经更新了,你能帮帮我吗?谢谢,你是对的,问题是关于“双引号”。 【参考方案1】:

我认为您的代码确实尝试生成 DotML(尽管使用了错误的命名空间),该语言的创建者有一个样式表,您可以导入以生成 Dot:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.martin-loetzsch.de/DOTML" version="3.0">
    <xsl:import href="http://www.martin-loetzsch.de/DOTML/dotml2dot.xsl"/>
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:variable name="dotml">
          <xsl:for-each select = "Import/Row">
            <graph file-name="graphs/node">
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                </node>   
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='items/subMenu[@name="pns"]/url'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='items/subMenu[@name="pns"]/url'/>
                    </xsl:attribute>
                </node>   
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='items/subMenu[@name="pppk"]/url'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='items/subMenu[@name="pppk"]/url'/>
                    </xsl:attribute>
                </node>   
                <node style="filled" fontsize="16">
                    <xsl:attribute name="id">
                        <xsl:value-of select='items/subMenu[@name="ppt"]/url'/>
                    </xsl:attribute>
                    <xsl:attribute name="label">
                        <xsl:value-of select='items/subMenu[@name="ppt"]/url'/>
                    </xsl:attribute>
                </node>  

                <edge fontname="Arial" fontsize="9" label="Permit">
                    <xsl:attribute name="from">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="to">
                        <xsl:value-of select='items/subMenu[@name="pns"]/url'/>
                    </xsl:attribute>
                </edge>   
                <edge fontname="Arial" fontsize="9" label="Permit">
                    <xsl:attribute name="from">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="to">
                        <xsl:value-of select='items/subMenu[@name="pppk"]/url'/>
                    </xsl:attribute>
                </edge>   
                <edge fontname="Arial" fontsize="9" label="Permit">
                    <xsl:attribute name="from">
                        <xsl:value-of select='role'/>
                    </xsl:attribute>
                    <xsl:attribute name="to">
                        <xsl:value-of select='items/subMenu[@name="ppt"]/url'/>
                    </xsl:attribute>
                </edge>   
            </graph>
          </xsl:for-each>         
        </xsl:variable>
        <xsl:apply-templates select="$dotml/node()"/>
      
    </xsl:template>    
</xsl:stylesheet>

我没有测试结果是否可以消费Graphviz。

【讨论】:

感谢马丁的回应,但是标签 中的 $dotml/node() 是什么,我应该写得完全一样在 xsl:apply-templates 标签中? @RafifFavian,是的,这只是尝试将您以前的样式表及其结果(存储在变量 &lt;xsl:variable name="dotml"&gt; 中)结合起来,然后应用从网站导入的样式表,希望将 DotML 转换为您的代码生成您的工具可以使用的点格式。 谢谢你的回复,你能看到我上面的问题吗,因为我的问题已经更新了,你能帮帮我吗?谢谢 尝试从结果中删除最后一行&lt;dot-filename&gt;graphs/node&lt;/dot-filename&gt;,然后测试文件是否可以被处理。 它是一样的...,仍然错误 C:\Users\rafif\Desktop\saxons>dot -Tpng policy.dot -o policy_dot.png 错误:policy.dot:第 1 行附近的语法错误'-'

以上是关于如何使用 saxonica 将 xml 转换为 graphviz的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 XSLT saxonica 将 xml 转换为点? [复制]

Saxonica EE Xslt 转换处理无限循环

Saxonica URIResolver 中的异常处理

xml转换为json格式时,如何将指定节点转换成数组 Json.NET

如何将 XML 转换为 java.util.Map,反之亦然?

使用 XSLT 将 XML 转换为 JSON