# 转 DELMIA Apriso XML 的步骤
直接生成符合 DELMIA Apriso 要求的 TransportPathOrders XML,跳过 XSLT 转换步骤。
简化方案:直接生成目标XML
目标Schema(直接使用)
创建文件 TransportPathOrder.xsd(这是唯一需要的Schema文件):
xml
复制
您的程序直接生成XML的代码
C# 示例(如果您用C#)
csharp
复制
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.IO;
public class TransportPathGenerator
{
public class PathPoint
{
public string Id { get; set; }
public string Name { get; set; }
public string Type { get; set; } // StartPoint, WayPoint, EndPoint
public int Index { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
public class PathEdge
{
public string Type { get; set; } // straight, arc
public double PhysicalLength { get; set; }
public TrajectoryInfo Trajectory { get; set; }
}
public class TrajectoryInfo
{
public Point3D StartTangent { get; set; }
public Point3D EndTangent { get; set; }
public Point3D ArcCenter { get; set; }
public double Radius { get; set; }
public double DeflectionAngle { get; set; }
}
public class Point3D
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
public void GenerateXml(
string orderId,
string orderName,
List points,
List edges,
string outputPath)
{
XNamespace ns = "http://www.dassaultsystemes.com/delmia/apriso";
// 构建Nodes
var nodesElement = new XElement(ns + "Nodes");
foreach (var point in points)
{
nodesElement.Add(new XElement(ns + "Node",
new XElement(ns + "NodeId", point.Id),
new XElement(ns + "SequenceId", point.Index),
new XElement(ns + "NodeName", point.Name),
new XElement(ns + "NodeType", point.Type),
new XElement(ns + "Position",
new XElement(ns + "X", point.X),
new XElement(ns + "Y", point.Y),
new XElement(ns + "Z", point.Z)
),
new XElement(ns + "Released", "true")
));
}
// 构建Edges(需要关联起点和终点ID)
var edgesElement = new XElement(ns + "Edges");
for (int i = 0; i < edges.Count; i++)
{
var edge = edges[i];
var startNode = points[i];
var endNode = points[i + 1];
var edgeElement = new XElement(ns + "Edge",
new XElement(ns + "EdgeId", $"edge_{i}"),
new XElement(ns + "EdgeType", edge.Type),
new XElement(ns + "SequenceId", i),
new XElement(ns + "StartNodeId", startNode.Id),
new XElement(ns + "EndNodeId", endNode.Id),
new XElement(ns + "PhysicalLength", edge.PhysicalLength)
);
// 如果是弧线,添加轨迹信息
if (edge.Type == "arc" && edge.Trajectory != null)
{
edgeElement.Add(new XElement(ns + "Trajectory",
new XElement(ns + "StartTangent",
new XElement(ns + "X", edge.Trajectory.StartTangent.X),
new XElement(ns + "Y", edge.Trajectory.StartTangent.Y),
new XElement(ns + "Z", edge.Trajectory.StartTangent.Z)
),
new XElement(ns + "EndTangent",
new XElement(ns + "X", edge.Trajectory.EndTangent.X),
new XElement(ns + "Y", edge.Trajectory.EndTangent.Y),
new XElement(ns + "Z", edge.Trajectory.EndTangent.Z)
),
new XElement(ns + "ArcCenter",
new XElement(ns + "X", edge.Trajectory.ArcCenter.X),
new XElement(ns + "Y", edge.Trajectory.ArcCenter.Y),
new XElement(ns + "Z", edge.Trajectory.ArcCenter.Z)
),
new XElement(ns + "Radius", edge.Trajectory.Radius),
new XElement(ns + "DeflectionAngle", edge.Trajectory.DeflectionAngle)
));
}
edgesElement.Add(edgeElement);
}
// 构建完整文档
var document = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement(ns + "TransportPathOrders",
new XElement(ns + "PathOrder",
new XElement(ns + "OrderId", orderId),
new XElement(ns + "OrderName", orderName),
new XElement(ns + "Description", "NavisworksTransport生成的路径"),
new XElement(ns + "PathType", "Ground"),
new XElement(ns + "TotalLength", CalculateTotalLength(edges)),
new XElement(ns + "Timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")),
new XElement(ns + "Generator", "NavisworksTransport"),
new XElement(ns + "Version", "1.0"),
nodesElement,
edgesElement,
new XElement(ns + "ObjectLimits",
new XElement(ns + "MaxLength", "0"),
new XElement(ns + "MaxWidth", "0"),
new XElement(ns + "MaxHeight", "0"),
new XElement(ns + "SafetyMargin", "0")
),
new XElement(ns + "CoordinateSystem", "Global")
)
)
);
document.Save(outputPath);
}
private double CalculateTotalLength(List edges)
{
double total = 0;
foreach (var edge in edges)
total += edge.PhysicalLength;
return total;
}
}
// 使用示例
class Program
{
static void Main()
{
var generator = new TransportPathGenerator();
var points = new List
{
new AGVPathGenerator.PathPoint
{
Id = "3ada559e-36b9-4537-b341-cfff765c8d43",
Name = "起点",
Type = "StartPoint",
Index = 0,
X = -152.614,
Y = 0.517,
Z = 14.833
},
new AGVPathGenerator.PathPoint
{
Id = "042229ba-0ce2-4f6c-af8f-57f840300e82",
Name = "路径点1",
Type = "WayPoint",
Index = 1,
X = -131.345,
Y = -14.532,
Z = 14.75
},
new AGVPathGenerator.PathPoint
{
Id = "69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5",
Name = "终点",
Type = "EndPoint",
Index = 2,
X = -55.369,
Y = -0.504,
Z = 14.833
}
};
var edges = new List
{
new AGVPathGenerator.PathEdge
{
Type = "straight",
PhysicalLength = 22.595
},
new AGVPathGenerator.PathEdge
{
Type = "arc",
PhysicalLength = 6.548,
Trajectory = new AGVPathGenerator.TrajectoryInfo
{
StartTangent = new AGVPathGenerator.Point3D
{ X = -134.17, Y = -12.533, Z = 14.761 },
EndTangent = new AGVPathGenerator.Point3D
{ X = -127.943, Y = -13.903, Z = 14.754 },
ArcCenter = new AGVPathGenerator.Point3D
{ X = -129.432, Y = -5.837, Z = 14.799 },
Radius = 8.202,
DeflectionAngle = 0.798
}
},
new AGVPathGenerator.PathEdge
{
Type = "straight",
PhysicalLength = 73.8
}
};
generator.GenerateXml(
"17838e6e-1112-4e62-a3ab-d7a3354d39d3",
"人工_0219_203325",
points,
edges,
"output.xml"
);
}
}
Python 示例(如果您用Python)
Python
复制
import xml.etree.ElementTree as ET
from datetime import datetime
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class Point3D:
x: float
y: float
z: float
@dataclass
class TrajectoryInfo:
start_tangent: Point3D
end_tangent: Point3D
arc_center: Point3D
radius: float
deflection_angle: float
@dataclass
class PathPoint:
id: str
name: str
type: str # StartPoint, WayPoint, EndPoint
index: int
x: float
y: float
z: float
@dataclass
class PathEdge:
edge_type: str # straight, arc
physical_length: float
trajectory: Optional[TrajectoryInfo] = None
class TransportPathGenerator:
def __init__(self):
self.ns = "http://www.dassaultsystemes.com/delmia/apriso"
ET.register_namespace('', self.ns)
def generate_xml(self,
order_id: str,
order_name: str,
points: List[PathPoint],
edges: List[PathEdge],
output_path: str):
# 创建根元素
root = ET.Element(f"{{{self.ns}}}TransportPathOrders")
# 创建PathOrder
path_order = ET.SubElement(root, f"{{{self.ns}}}PathOrder")
# 基础信息
ET.SubElement(path_order, f"{{{self.ns}}}OrderId").text = order_id
ET.SubElement(path_order, f"{{{self.ns}}}OrderName").text = order_name
ET.SubElement(path_order, f"{{{self.ns}}}Description").text = "NavisworksTransport生成的路径"
ET.SubElement(path_order, f"{{{self.ns}}}PathType").text = "Ground"
ET.SubElement(path_order, f"{{{self.ns}}}TotalLength").text = str(sum(e.physical_length for e in edges))
ET.SubElement(path_order, f"{{{self.ns}}}Timestamp").text = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
ET.SubElement(path_order, f"{{{self.ns}}}Generator").text = "NavisworksTransport"
ET.SubElement(path_order, f"{{{self.ns}}}Version").text = "1.0"
# 创建Nodes
nodes = ET.SubElement(path_order, f"{{{self.ns}}}Nodes")
for point in points:
node = ET.SubElement(nodes, f"{{{self.ns}}}Node")
ET.SubElement(node, f"{{{self.ns}}}NodeId").text = point.id
ET.SubElement(node, f"{{{self.ns}}}SequenceId").text = str(point.index)
ET.SubElement(node, f"{{{self.ns}}}NodeName").text = point.name
ET.SubElement(node, f"{{{self.ns}}}NodeType").text = point.type
position = ET.SubElement(node, f"{{{self.ns}}}Position")
ET.SubElement(position, f"{{{self.ns}}}X").text = str(point.x)
ET.SubElement(position, f"{{{self.ns}}}Y").text = str(point.y)
ET.SubElement(position, f"{{{self.ns}}}Z").text = str(point.z)
ET.SubElement(node, f"{{{self.ns}}}Released").text = "true"
# 创建Edges
edges_elem = ET.SubElement(path_order, f"{{{self.ns}}}Edges")
for i, edge in enumerate(edges):
edge_elem = ET.SubElement(edges_elem, f"{{{self.ns}}}Edge")
ET.SubElement(edge_elem, f"{{{self.ns}}}EdgeId").text = f"edge_{i}"
ET.SubElement(edge_elem, f"{{{self.ns}}}EdgeType").text = edge.edge_type
ET.SubElement(edge_elem, f"{{{self.ns}}}SequenceId").text = str(i)
ET.SubElement(edge_elem, f"{{{self.ns}}}StartNodeId").text = points[i].id
ET.SubElement(edge_elem, f"{{{self.ns}}}EndNodeId").text = points[i+1].id
ET.SubElement(edge_elem, f"{{{self.ns}}}PhysicalLength").text = str(edge.physical_length)
# 如果是弧线,添加轨迹
if edge.edge_type == "arc" and edge.trajectory:
traj = ET.SubElement(edge_elem, f"{{{self.ns}}}Trajectory")
start_tan = ET.SubElement(traj, f"{{{self.ns}}}StartTangent")
ET.SubElement(start_tan, f"{{{self.ns}}}X").text = str(edge.trajectory.start_tangent.x)
ET.SubElement(start_tan, f"{{{self.ns}}}Y").text = str(edge.trajectory.start_tangent.y)
ET.SubElement(start_tan, f"{{{self.ns}}}Z").text = str(edge.trajectory.start_tangent.z)
end_tan = ET.SubElement(traj, f"{{{self.ns}}}EndTangent")
ET.SubElement(end_tan, f"{{{self.ns}}}X").text = str(edge.trajectory.end_tangent.x)
ET.SubElement(end_tan, f"{{{self.ns}}}Y").text = str(edge.trajectory.end_tangent.y)
ET.SubElement(end_tan, f"{{{self.ns}}}Z").text = str(edge.trajectory.end_tangent.z)
arc_center = ET.SubElement(traj, f"{{{self.ns}}}ArcCenter")
ET.SubElement(arc_center, f"{{{self.ns}}}X").text = str(edge.trajectory.arc_center.x)
ET.SubElement(arc_center, f"{{{self.ns}}}Y").text = str(edge.trajectory.arc_center.y)
ET.SubElement(arc_center, f"{{{self.ns}}}Z").text = str(edge.trajectory.arc_center.z)
ET.SubElement(traj, f"{{{self.ns}}}Radius").text = str(edge.trajectory.radius)
ET.SubElement(traj, f"{{{self.ns}}}DeflectionAngle").text = str(edge.trajectory.deflection_angle)
# 对象限制
limits = ET.SubElement(path_order, f"{{{self.ns}}}ObjectLimits")
ET.SubElement(limits, f"{{{self.ns}}}MaxLength").text = "0"
ET.SubElement(limits, f"{{{self.ns}}}MaxWidth").text = "0"
ET.SubElement(limits, f"{{{self.ns}}}MaxHeight").text = "0"
ET.SubElement(limits, f"{{{self.ns}}}SafetyMargin").text = "0"
ET.SubElement(path_order, f"{{{self.ns}}}CoordinateSystem").text = "Global"
# 保存文件
tree = ET.ElementTree(root)
tree.write(output_path, encoding='utf-8', xml_declaration=True)
print(f"XML已生成: {output_path}")
# 使用示例
if __name__ == "__main__":
generator = TransportPathGenerator()
points = [
PathPoint("3ada559e-36b9-4537-b341-cfff765c8d43", "起点", "StartPoint", 0, -152.614, 0.517, 14.833),
PathPoint("042229ba-0ce2-4f6c-af8f-57f840300e82", "路径点1", "WayPoint", 1, -131.345, -14.532, 14.75),
PathPoint("69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5", "终点", "EndPoint", 2, -55.369, -0.504, 14.833)
]
edges = [
PathEdge("straight", 22.595),
PathEdge("arc", 6.548, TrajectoryInfo(
Point3D(-134.17, -12.533, 14.761),
Point3D(-127.943, -13.903, 14.754),
Point3D(-129.432, -5.837, 14.799),
8.202, 0.798
)),
PathEdge("straight", 73.8)
]
generator.generate_xml(
"17838e6e-1112-4e62-a3ab-d7a3354d39d3",
"人工_0219_203325",
points,
edges,
"transport_path.xml"
)
生成的 XML 示例
xml
复制
17838e6e-1112-4e62-a3ab-d7a3354d39d3
人工_0219_203325
NavisworksTransport生成的路径
Ground
102.943
2026-03-09T16:30:45Z
NavisworksTransport
1.0
3ada559e-36b9-4537-b341-cfff765c8d43
0
起点
StartPoint
-152.614
0.517
14.833
true
042229ba-0ce2-4f6c-af8f-57f840300e82
1
路径点1
WayPoint
-131.345
-14.532
14.75
true
69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5
2
终点
EndPoint
-55.369
-0.504
14.833
true
edge_0
straight
0
3ada559e-36b9-4537-b341-cfff765c8d43
042229ba-0ce2-4f6c-af8f-57f840300e82
22.595
edge_1
arc
1
042229ba-0ce2-4f6c-af8f-57f840300e82
69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5
6.548
-134.17
-12.533
14.761
-127.943
-13.903
14.754
-129.432
-5.837
14.799
8.202
0.798
edge_2
straight
2
69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5
终点_D
73.8
0
0
0
0
Global
DELMIA Apriso 配置(简化版)
既然您直接生成目标XML,配置也简化了:
1. 部署Schema
将 TransportPathOrder.xsd 复制到:
plain
复制
SchemaRepository/XMLSchemas/FlexNet/TransportPathOrder.xsd
2. Routing Configuration(仅需路由,无需XSLT)
xml
复制
注意:不需要 Mapping Configuration,因为您直接生成了 Apriso 内部格式!
3. 创建Job Action处理程序
在DELMIA Apriso中创建 ProcessTransportPathOrder 来处理导入的路径数据。
关键优势
✅ 无需 XSLT 转换:直接生成目标格式,性能更好
✅ 配置更简单:只需配置路由,无需映射
✅ 数据完整性:保留所有原始信息(轨迹、切线等)
✅ 支持吊装路径:扩展了 LiftPoint/DescendPoint/HoverPoint 等节点类型
✅ 符合 Schema:遵循 TransportPathOrders.xsd 规范
您需要:
1. 把上面的 C# 或 Python 代码集成到您的程序中(或直接使用插件的导出功能)
2. 部署 XSD 文件到 Apriso
3. 配置简单的路由规则
4. 开发 Job Action 处理程序
> 注:插件已内置 ExportToDelmiaAprisoXml() 方法,在导出对话框中选择 `.delmiaxml` 格式即可直接生成符合该 Schema 的 XML 文件。