2016-07-31 6 views
0

Ich habe die folgende XML-Datei test.graphml, die ich mit dem XML-Paket in R.hinzufügen Kinder zu vorhandenen Knoten R unter Verwendung von XML

<?xml version="1.0" encoding="UTF-8"?> 
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns 
    http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> 
    <graph id="G" edgedefault="directed"> 
    <node id="n0"/> 
    <node id="n1"/> 
    <node id="n2"/> 
    <node id="n3"/> 
    <node id="n4"/> 
    <edge source="n0" target="n1"/> 
    <edge source="n0" target="n2"/> 
    <edge source="n2" target="n3"/> 
    <edge source="n1" target="n3"/> 
    <edge source="n3" target="n4"/> 
    </graph> 
</graphml> 

zu manipulieren versuche ich würde zu nisten Knoten N0 mögen, n1, n2 und n3 in einen neuen Graphknoten wie unten gezeigt.

<?xml version="1.0" encoding="UTF-8"?> 
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns 
    http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> 
    <graph id="G" edgedefault="directed"> 
    <graph id="g1"> 
     <node id="n0"/> 
     <node id="n1"/> 
     <node id="n2"/> 
     <node id="n3"/> 
    </graph> 
    <node id="n4"/> 
    <edge source="n0" target="n1"/> 
    <edge source="n0" target="n2"/> 
    <edge source="n2" target="n3"/> 
    <edge source="n1" target="n3"/> 
    <edge source="n3" target="n4"/> 
    </graph> 
</graphml> 

Der Code, den ich geschrieben habe, hat Unbekannten und Fehler, die ich nicht in der Lage bin wegen des Mangels an Erfahrung mit XML-Verarbeitung zu lösen. Ich würde sehr schätzen, dass einige Hinweise dazu helfen werden, fortzufahren.

library(XML) 

# Read file 
x <- xmlParse("test.graphml") 
ns <- c(graphml ="http://graphml.graphdrawing.org/xmlns") 

# Create new graph node 
ng <- xmlNode("graph", attrs = c("id" = "g1")) 

# Add n0-n3 as children of new graph node 
n0_n1_n2_n3 <- getNodeSet(x,"//graphml:node[@id = 'n0' or @id='n1' or @id='n2' or @id='n3']", namespaces = ns) 
ng <- append.xmlNode(ng, n0_n1_n2_n3) 

# Get only graph node 
g <- getNodeSet(x,"//graphml:graph", namespaces = ns) 

# Remove nodes n0-n3 from the only graph node 
# How I do this? 
# This did not work: removeNodes(g, n0_n1_n2_n3) 

# Add new graph node as child of only graph node  
g <- append.xmlNode(g, ng) 
    #! Error message: 
    Error in UseMethod("append") : 
    no applicable method for 'append' applied to an object of class "XMLNodeSet" 

Antwort

1

Betrachten Sie XSLT, die spezielle Sprache zum Transformieren von XML-Dateien. Da Sie eine Änderung des XML-Codes benötigen (Hinzufügen eines übergeordneten Knotens in einer ausgewählten Gruppe von untergeordneten Elementen) und durch ein nicht deklariertes Namespacepräfix (xmlns="http://graphml.graphdrawing.org/xmlns") navigieren müssen, ist XSLT eine optimale Lösung.

Allerdings verfügt R über kein vollständig kompatibles XSL-Modul für die Ausführung von XSLT 1.0-Skripten wie andere allgemeine Sprachen (Java, PHP, Python). Nichtsdestotrotz kann R externe Programme (einschließlich der oben genannten Sprachen) oder dedizierte XSLT-Prozessoren (Xalan, Saxon) aufrufen oder Befehlszeileninterpreter einschließlich PowerShell und xsltproc des Terminals unter Verwendung von system() aufrufen. Unten sind letztere Lösungen.

XSLT(speichern als .xsl, in R-Skript referenziert werden)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:doc="http://graphml.graphdrawing.org/xmlns" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">  
    <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="doc:graphml"> 
    <xsl:copy> 
     <xsl:copy-of select="document('')/*/@xsi:schemaLocation"/> 
     <xsl:apply-templates select="doc:graph"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="doc:graph"> 
    <xsl:element name="{local-name()}" namespace="http://graphml.graphdrawing.org/xmlns"> 
     <xsl:apply-templates select="@*"/> 
     <xsl:element name="graph" namespace="http://graphml.graphdrawing.org/xmlns"> 
     <xsl:attribute name="id">g1</xsl:attribute> 
     <xsl:apply-templates select="doc:node[position() &lt; 5]"/> 
     </xsl:element> 
     <xsl:apply-templates select="doc:node[@id='n4']|doc:edge"/> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template match="doc:graph/@*"> 
    <xsl:attribute name="{local-name()}"><xsl:value-of select="."/></xsl:attribute> 
    </xsl:template> 

    <xsl:template match="doc:node|doc:edge"> 
    <xsl:element name="{local-name()}" namespace="http://graphml.graphdrawing.org/xmlns"> 
     <xsl:attribute name="{local-name(@*)}"><xsl:value-of select="@*"/></xsl:attribute> 
    </xsl:element> 
    </xsl:template>  
</xsl:stylesheet> 

Powershell-Skript(für Windows PC-Nutzer, wie XMLTransform.ps1 speichern)

param ($xml, $xsl, $output) 

if (-not $xml -or -not $xsl -or -not $output) { 
    Write-Host "& .\xslt.ps1 [-xml] xml-input [-xsl] xsl-input [-output] transform-output" 
    exit; 
} 

trap [Exception]{ 
    Write-Host $_.Exception; 
} 

$xslt = New-Object System.Xml.Xsl.XslCompiledTransform; 
$xslt.Load($xsl); 
$xslt.Transform($xml, $output); 

Write-Host "generated" $output; 

R Script (Aufruf Befehlszeilenoperationen)

library(XML) 

# WINDOWS USERS 
ps <- '"C:\\Path\\To\\XMLTransform.ps1"' # POWER SHELL SCRIPT 
input <- '"C:\\Path\\To\\Input.xml"'  # XML SOURCE 
xsl <- '"C:\\Path\\To\\XSLTScript.xsl"' # XSLT SCRIPT 
output <- '"C:\\Path\\To\\Output.xml"' # BLANK, EMPTY FILE PATH TO BE CREATED 

system(paste('Powershell.exe -executionpolicy remotesigned -File', 
      ps, input, xsl, output))    # NOTE SECURITY BYPASS ARGS 
doc <- xmlParse("C:\\Path\\To\\Output.xml") 

# UNIX (MAC/LINUX) USERS 
system("xsltproc /path/to/XSLTScript.xsl /path/to/input.xml -o /path/to/output.xml") 
doc <- xmlParse("/path/to/output.xml") 

print(doc)  
# <?xml version="1.0" encoding="utf-8"?> 
# <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> 
# <graph id="G" edgedefault="directed"> 
#  <graph id="g1"> 
#  <node id="n0"/> 
#  <node id="n1"/> 
#  <node id="n2"/> 
#  <node id="n3"/> 
#  </graph> 
#  <node id="n4"/> 
#  <edge source="n0"/> 
#  <edge source="n0"/> 
#  <edge source="n2"/> 
#  <edge source="n1"/> 
#  <edge source="n3"/> 
# </graph> 
# </graphml> 
+0

Ausgezeichnete ausführliche Antwort! Ich werde Zeit investieren, um XLST zu lernen. – nandu

Verwandte Themen