增加导出为Delmia兼容的xml格式

This commit is contained in:
tian 2026-03-09 17:47:39 +08:00
parent 486caf1c38
commit 0f669fd995
6 changed files with 1193 additions and 18 deletions

View File

@ -0,0 +1,650 @@
# 转 DELMIA Apriso XML 的步骤
直接生成符合 DELMIA Apriso 要求的 TransportPathOrders XML跳过 XSLT 转换步骤。
简化方案直接生成目标XML
目标Schema直接使用
创建文件 TransportPathOrder.xsd这是唯一需要的Schema文件
xml
复制
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:apr="http://www.dassaultsystemes.com/delmia/apriso"
targetNamespace="http://www.dassaultsystemes.com/delmia/apriso"
elementFormDefault="qualified">
<xs:element name="TransportPathOrders" type="apr:TransportPathOrdersType"/>
<xs:complexType name="TransportPathOrdersType">
<xs:sequence>
<xs:element name="PathOrder" type="apr:PathOrderType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PathOrderType">
<xs:sequence>
<xs:element name="OrderId" type="xs:string"/>
<xs:element name="OrderName" type="xs:string"/>
<xs:element name="Description" type="xs:string"/>
<xs:element name="PathType" type="xs:string"/>
<xs:element name="TotalLength" type="xs:decimal"/>
<xs:element name="Timestamp" type="xs:dateTime"/>
<xs:element name="Generator" type="xs:string"/>
<xs:element name="Version" type="xs:string"/>
<xs:element name="Nodes" type="apr:NodesType"/>
<xs:element name="Edges" type="apr:EdgesType"/>
<xs:element name="ObjectLimits" type="apr:ObjectLimitsType"/>
<xs:element name="CoordinateSystem" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NodesType">
<xs:sequence>
<xs:element name="Node" type="apr:NodeType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NodeType">
<xs:sequence>
<xs:element name="NodeId" type="xs:string"/>
<xs:element name="SequenceId" type="xs:int"/>
<xs:element name="NodeName" type="xs:string"/>
<xs:element name="NodeType" type="apr:NodeTypeEnum"/>
<xs:element name="Position" type="apr:PositionType"/>
<xs:element name="Released" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="NodeTypeEnum">
<xs:restriction base="xs:string">
<xs:enumeration value="StartPoint"/>
<xs:enumeration value="WayPoint"/>
<xs:enumeration value="EndPoint"/>
<xs:enumeration value="ChargePoint"/>
<xs:enumeration value="ParkPoint"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="PositionType">
<xs:sequence>
<xs:element name="X" type="xs:decimal"/>
<xs:element name="Y" type="xs:decimal"/>
<xs:element name="Z" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="EdgesType">
<xs:sequence>
<xs:element name="Edge" type="apr:EdgeType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="EdgeType">
<xs:sequence>
<xs:element name="EdgeId" type="xs:string"/>
<xs:element name="EdgeType" type="apr:EdgeTypeEnum"/>
<xs:element name="SequenceId" type="xs:int"/>
<xs:element name="StartNodeId" type="xs:string"/>
<xs:element name="EndNodeId" type="xs:string"/>
<xs:element name="PhysicalLength" type="xs:decimal"/>
<xs:element name="Trajectory" type="apr:TrajectoryType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="EdgeTypeEnum">
<xs:restriction base="xs:string">
<xs:enumeration value="straight"/>
<xs:enumeration value="arc"/>
<xs:enumeration value="bezier"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TrajectoryType">
<xs:sequence>
<xs:element name="StartTangent" type="apr:PositionType"/>
<xs:element name="EndTangent" type="apr:PositionType"/>
<xs:element name="ArcCenter" type="apr:PositionType" minOccurs="0"/>
<xs:element name="Radius" type="xs:decimal" minOccurs="0"/>
<xs:element name="DeflectionAngle" type="xs:decimal" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ObjectLimitsType">
<xs:sequence>
<xs:element name="MaxLength" type="xs:decimal"/>
<xs:element name="MaxWidth" type="xs:decimal"/>
<xs:element name="MaxHeight" type="xs:decimal"/>
<xs:element name="SafetyMargin" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
您的程序直接生成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<PathPoint> points,
List<PathEdge> 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<PathEdge> 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<TransportPathGenerator.PathPoint>
{
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<TransportPathGenerator.PathEdge>
{
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
复制
<?xml version='1.0' encoding='utf-8'?>
<TransportPathOrders xmlns="http://www.dassaultsystemes.com/delmia/apriso">
<PathOrder>
<OrderId>17838e6e-1112-4e62-a3ab-d7a3354d39d3</OrderId>
<OrderName>人工_0219_203325</OrderName>
<Description>NavisworksTransport生成的路径</Description>
<PathType>Ground</PathType>
<TotalLength>102.943</TotalLength>
<Timestamp>2026-03-09T16:30:45Z</Timestamp>
<Generator>NavisworksTransport</Generator>
<Version>1.0</Version>
<Nodes>
<Node>
<NodeId>3ada559e-36b9-4537-b341-cfff765c8d43</NodeId>
<SequenceId>0</SequenceId>
<NodeName>起点</NodeName>
<NodeType>StartPoint</NodeType>
<Position>
<X>-152.614</X>
<Y>0.517</Y>
<Z>14.833</Z>
</Position>
<Released>true</Released>
</Node>
<Node>
<NodeId>042229ba-0ce2-4f6c-af8f-57f840300e82</NodeId>
<SequenceId>1</SequenceId>
<NodeName>路径点1</NodeName>
<NodeType>WayPoint</NodeType>
<Position>
<X>-131.345</X>
<Y>-14.532</Y>
<Z>14.75</Z>
</Position>
<Released>true</Released>
</Node>
<Node>
<NodeId>69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5</NodeId>
<SequenceId>2</SequenceId>
<NodeName>终点</NodeName>
<NodeType>EndPoint</NodeType>
<Position>
<X>-55.369</X>
<Y>-0.504</Y>
<Z>14.833</Z>
</Position>
<Released>true</Released>
</Node>
</Nodes>
<Edges>
<Edge>
<EdgeId>edge_0</EdgeId>
<EdgeType>straight</EdgeType>
<SequenceId>0</SequenceId>
<StartNodeId>3ada559e-36b9-4537-b341-cfff765c8d43</StartNodeId>
<EndNodeId>042229ba-0ce2-4f6c-af8f-57f840300e82</EndNodeId>
<PhysicalLength>22.595</PhysicalLength>
</Edge>
<Edge>
<EdgeId>edge_1</EdgeId>
<EdgeType>arc</EdgeType>
<SequenceId>1</SequenceId>
<StartNodeId>042229ba-0ce2-4f6c-af8f-57f840300e82</StartNodeId>
<EndNodeId>69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5</EndNodeId>
<PhysicalLength>6.548</PhysicalLength>
<Trajectory>
<StartTangent>
<X>-134.17</X>
<Y>-12.533</Y>
<Z>14.761</Z>
</StartTangent>
<EndTangent>
<X>-127.943</X>
<Y>-13.903</Y>
<Z>14.754</Z>
</EndTangent>
<ArcCenter>
<X>-129.432</X>
<Y>-5.837</Y>
<Z>14.799</Z>
</ArcCenter>
<Radius>8.202</Radius>
<DeflectionAngle>0.798</DeflectionAngle>
</Trajectory>
</Edge>
<Edge>
<EdgeId>edge_2</EdgeId>
<EdgeType>straight</EdgeType>
<SequenceId>2</SequenceId>
<StartNodeId>69fa7321-3dc5-4ec5-9c1f-74e2a6d787a5</StartNodeId>
<EndNodeId>终点_D</EndNodeId> <!-- 修正最后一条边的终点应该是终点D -->
<PhysicalLength>73.8</PhysicalLength>
</Edge>
</Edges>
<ObjectLimits>
<MaxLength>0</MaxLength>
<MaxWidth>0</MaxWidth>
<MaxHeight>0</MaxHeight>
<SafetyMargin>0</SafetyMargin>
</ObjectLimits>
<CoordinateSystem>Global</CoordinateSystem>
</PathOrder>
</TransportPathOrders>
DELMIA Apriso 配置(简化版)
既然您直接生成目标XML配置也简化了
1. 部署Schema
将 TransportPathOrder.xsd 复制到:
plain
复制
SchemaRepository/XMLSchemas/FlexNet/TransportPathOrder.xsd
2. Routing Configuration仅需路由无需XSLT
xml
复制
<Routing>
<Route
FromSchema="TransportPathOrders"
RouteTo="ProcessAGVPathOrder"
AlertName=""/>
</Routing>
注意:不需要 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 文件。

View File

@ -2,6 +2,12 @@
## 功能点
### [2026/3/9]
1. [x] (功能)支持记录并查看路径文件操作的历史记录
2. [x] (优化)物流自定义类别配置,简化并合并到系统配置中
3. [x] 优化给版本号增加时间戳增加Build号
### [2026/2/24]
1. [x] (优化)吊装路径支持多个水平层

View File

@ -154,6 +154,9 @@ namespace NavisworksTransport.Commands
case ExportFormat.Csv:
expectedExtensions = new[] { ".csv" };
break;
case ExportFormat.DelmiaApriso:
expectedExtensions = new[] { ".aprxml" };
break;
default:
expectedExtensions = new[] { ".xml" };
break;
@ -440,9 +443,14 @@ namespace NavisworksTransport.Commands
{
success = _pathDataManager.ExportToCsv(pathsToExport, _parameters.OutputFilePath, _parameters.ExportSettings);
}
else if (_parameters.ExportFormat == ExportFormat.DelmiaApriso)
{
// DELMIA Apriso格式TransportPathOrders Schema
success = _pathDataManager.ExportToDelmiaAprisoXml(pathsToExport, _parameters.OutputFilePath, _parameters.ExportSettings);
}
else
{
// DELMIA格式
// 旧版DELMIA格式
success = _pathDataManager.ExportDelmiaFormat(pathsToExport, _parameters.OutputFilePath, _parameters.ExportSettings);
}

View File

@ -766,6 +766,378 @@ namespace NavisworksTransport
}
}
/// <summary>
/// 导出路径到DELMIA Apriso XML格式符合TransportPathOrders Schema
/// </summary>
/// <param name="routes">路径集合</param>
/// <param name="filePath">文件路径</param>
/// <param name="exportSettings">导出设置</param>
/// <returns>是否成功</returns>
public bool ExportToDelmiaAprisoXml(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
{
if (routes == null || routes.Count == 0)
{
throw new ArgumentException("路径集合不能为空");
}
try
{
LogManager.Info($"[路径文件操作] 开始导出 {routes.Count} 条路径到DELMIA Apriso XML文件: {filePath}");
// 确保导出目录存在
var directory = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
var xmlDoc = new XmlDocument();
var declaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
xmlDoc.AppendChild(declaration);
// DELMIA Apriso命名空间
const string ns = "http://www.dassaultsystemes.com/delmia/apriso";
const string nsPrefix = "apr";
// 创建根元素 TransportPathOrders
var rootElement = xmlDoc.CreateElement(nsPrefix, "TransportPathOrders", ns);
xmlDoc.AppendChild(rootElement);
// 为每个路径创建PathOrder
foreach (var route in routes.Where(r => r.IsValid()))
{
var pathOrderElement = CreateDelmiaAprisoPathOrderElement(xmlDoc, route, exportSettings, ns, nsPrefix);
rootElement.AppendChild(pathOrderElement);
}
// 保存文件
using (var writer = new XmlTextWriter(filePath, Encoding.UTF8))
{
writer.Formatting = Formatting.Indented;
writer.Indentation = 2;
xmlDoc.WriteTo(writer);
}
LogManager.Info($"[路径文件操作] 成功导出 {routes.Count} 条路径到DELMIA Apriso XML文件: {filePath}");
return true;
}
catch (Exception ex)
{
LogManager.Error($"[路径文件操作] 导出DELMIA Apriso XML文件失败: {ex.Message}", ex);
return false;
}
}
/// <summary>
/// 创建DELMIA Apriso格式的PathOrder元素
/// </summary>
private XmlElement CreateDelmiaAprisoPathOrderElement(XmlDocument xmlDoc, PathRoute route, ExportSettings settings, string ns, string nsPrefix)
{
var pathOrderElement = xmlDoc.CreateElement(nsPrefix, "PathOrder", ns);
// 基础信息
var orderIdElement = xmlDoc.CreateElement(nsPrefix, "OrderId", ns);
orderIdElement.InnerText = route.Id ?? Guid.NewGuid().ToString();
pathOrderElement.AppendChild(orderIdElement);
var orderNameElement = xmlDoc.CreateElement(nsPrefix, "OrderName", ns);
orderNameElement.InnerText = route.Name ?? "未命名路径";
pathOrderElement.AppendChild(orderNameElement);
var descriptionElement = xmlDoc.CreateElement(nsPrefix, "Description", ns);
descriptionElement.InnerText = route.Description ?? $"NavisworksTransport生成的路径: {route.Name}";
pathOrderElement.AppendChild(descriptionElement);
var pathTypeElement = xmlDoc.CreateElement(nsPrefix, "PathType", ns);
pathTypeElement.InnerText = MapToDelmiaPathType(route.PathType);
pathOrderElement.AppendChild(pathTypeElement);
var totalLengthElement = xmlDoc.CreateElement(nsPrefix, "TotalLength", ns);
totalLengthElement.InnerText = route.TotalLength.ToString("F3", CultureInfo.InvariantCulture);
pathOrderElement.AppendChild(totalLengthElement);
var timestampElement = xmlDoc.CreateElement(nsPrefix, "Timestamp", ns);
timestampElement.InnerText = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
pathOrderElement.AppendChild(timestampElement);
var generatorElement = xmlDoc.CreateElement(nsPrefix, "Generator", ns);
generatorElement.InnerText = "NavisworksTransport";
pathOrderElement.AppendChild(generatorElement);
var versionElement = xmlDoc.CreateElement(nsPrefix, "Version", ns);
versionElement.InnerText = "1.0";
pathOrderElement.AppendChild(versionElement);
// 创建Nodes
var nodesElement = xmlDoc.CreateElement(nsPrefix, "Nodes", ns);
pathOrderElement.AppendChild(nodesElement);
var sortedPoints = route.GetSortedPoints();
for (int i = 0; i < sortedPoints.Count; i++)
{
var point = sortedPoints[i];
var nodeElement = xmlDoc.CreateElement(nsPrefix, "Node", ns);
// NodeId
var nodeIdElement = xmlDoc.CreateElement(nsPrefix, "NodeId", ns);
nodeIdElement.InnerText = point.Id ?? $"node_{i}";
nodeElement.AppendChild(nodeIdElement);
// SequenceId
var sequenceIdElement = xmlDoc.CreateElement(nsPrefix, "SequenceId", ns);
sequenceIdElement.InnerText = i.ToString();
nodeElement.AppendChild(sequenceIdElement);
// NodeName
var nodeNameElement = xmlDoc.CreateElement(nsPrefix, "NodeName", ns);
nodeNameElement.InnerText = point.Name ?? $"点{i}";
nodeElement.AppendChild(nodeNameElement);
// NodeType (映射到DELMIA枚举支持吊装路径特殊类型)
var nodeTypeElement = xmlDoc.CreateElement(nsPrefix, "NodeType", ns);
string nodeType = MapToDelmiaNodeType(point.Type, route.PathType, i, sortedPoints.Count);
nodeTypeElement.InnerText = nodeType;
nodeElement.AppendChild(nodeTypeElement);
// 吊装路径特殊属性LiftHeight (仅对LiftPoint和HoverPoint)
if ((nodeType == "LiftPoint" || nodeType == "HoverPoint") && route.LiftHeight > 0)
{
var liftHeightElement = xmlDoc.CreateElement(nsPrefix, "LiftHeight", ns);
liftHeightElement.InnerText = route.LiftHeight.ToString("F3", CultureInfo.InvariantCulture);
nodeElement.AppendChild(liftHeightElement);
}
// Position
var positionElement = xmlDoc.CreateElement(nsPrefix, "Position", ns);
var xElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
xElement.InnerText = point.Position.X.ToString("F3", CultureInfo.InvariantCulture);
positionElement.AppendChild(xElement);
var yElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
yElement.InnerText = point.Position.Y.ToString("F3", CultureInfo.InvariantCulture);
positionElement.AppendChild(yElement);
var zElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
zElement.InnerText = point.Position.Z.ToString("F3", CultureInfo.InvariantCulture);
positionElement.AppendChild(zElement);
nodeElement.AppendChild(positionElement);
// Released
var releasedElement = xmlDoc.CreateElement(nsPrefix, "Released", ns);
releasedElement.InnerText = "true";
nodeElement.AppendChild(releasedElement);
nodesElement.AppendChild(nodeElement);
}
// 创建Edges
var edgesElement = xmlDoc.CreateElement(nsPrefix, "Edges", ns);
pathOrderElement.AppendChild(edgesElement);
if (route.Edges != null && route.Edges.Count > 0)
{
for (int i = 0; i < route.Edges.Count && i < sortedPoints.Count - 1; i++)
{
var edge = route.Edges[i];
var startNode = sortedPoints[i];
var endNode = sortedPoints[i + 1];
var edgeElement = xmlDoc.CreateElement(nsPrefix, "Edge", ns);
// EdgeId
var edgeIdElement = xmlDoc.CreateElement(nsPrefix, "EdgeId", ns);
edgeIdElement.InnerText = $"edge_{i}";
edgeElement.AppendChild(edgeIdElement);
// EdgeType (支持吊装路径特殊类型)
var edgeTypeElement = xmlDoc.CreateElement(nsPrefix, "EdgeType", ns);
string edgeType = MapToDelmiaEdgeType(edge.SegmentType, route.PathType);
edgeTypeElement.InnerText = edgeType;
edgeElement.AppendChild(edgeTypeElement);
// SequenceId
var edgeSeqIdElement = xmlDoc.CreateElement(nsPrefix, "SequenceId", ns);
edgeSeqIdElement.InnerText = i.ToString();
edgeElement.AppendChild(edgeSeqIdElement);
// StartNodeId
var startNodeIdElement = xmlDoc.CreateElement(nsPrefix, "StartNodeId", ns);
startNodeIdElement.InnerText = startNode.Id ?? $"node_{i}";
edgeElement.AppendChild(startNodeIdElement);
// EndNodeId
var endNodeIdElement = xmlDoc.CreateElement(nsPrefix, "EndNodeId", ns);
endNodeIdElement.InnerText = endNode.Id ?? $"node_{i + 1}";
edgeElement.AppendChild(endNodeIdElement);
// PhysicalLength
var physicalLengthElement = xmlDoc.CreateElement(nsPrefix, "PhysicalLength", ns);
physicalLengthElement.InnerText = edge.PhysicalLength.ToString("F3", CultureInfo.InvariantCulture);
edgeElement.AppendChild(physicalLengthElement);
// Trajectory (如果是弧线)
if (edge.SegmentType == PathSegmentType.Arc && edge.Trajectory != null)
{
var trajectoryElement = xmlDoc.CreateElement(nsPrefix, "Trajectory", ns);
// StartTangent
var startTangentElement = xmlDoc.CreateElement(nsPrefix, "StartTangent", ns);
var stXElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
stXElement.InnerText = edge.Trajectory.Ts.X.ToString("F3", CultureInfo.InvariantCulture);
startTangentElement.AppendChild(stXElement);
var stYElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
stYElement.InnerText = edge.Trajectory.Ts.Y.ToString("F3", CultureInfo.InvariantCulture);
startTangentElement.AppendChild(stYElement);
var stZElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
stZElement.InnerText = edge.Trajectory.Ts.Z.ToString("F3", CultureInfo.InvariantCulture);
startTangentElement.AppendChild(stZElement);
trajectoryElement.AppendChild(startTangentElement);
// EndTangent
var endTangentElement = xmlDoc.CreateElement(nsPrefix, "EndTangent", ns);
var etXElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
etXElement.InnerText = edge.Trajectory.Te.X.ToString("F3", CultureInfo.InvariantCulture);
endTangentElement.AppendChild(etXElement);
var etYElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
etYElement.InnerText = edge.Trajectory.Te.Y.ToString("F3", CultureInfo.InvariantCulture);
endTangentElement.AppendChild(etYElement);
var etZElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
etZElement.InnerText = edge.Trajectory.Te.Z.ToString("F3", CultureInfo.InvariantCulture);
endTangentElement.AppendChild(etZElement);
trajectoryElement.AppendChild(endTangentElement);
// ArcCenter
var arcCenterElement = xmlDoc.CreateElement(nsPrefix, "ArcCenter", ns);
var acXElement = xmlDoc.CreateElement(nsPrefix, "X", ns);
acXElement.InnerText = edge.Trajectory.ArcCenter.X.ToString("F3", CultureInfo.InvariantCulture);
arcCenterElement.AppendChild(acXElement);
var acYElement = xmlDoc.CreateElement(nsPrefix, "Y", ns);
acYElement.InnerText = edge.Trajectory.ArcCenter.Y.ToString("F3", CultureInfo.InvariantCulture);
arcCenterElement.AppendChild(acYElement);
var acZElement = xmlDoc.CreateElement(nsPrefix, "Z", ns);
acZElement.InnerText = edge.Trajectory.ArcCenter.Z.ToString("F3", CultureInfo.InvariantCulture);
arcCenterElement.AppendChild(acZElement);
trajectoryElement.AppendChild(arcCenterElement);
// Radius
var radiusElement = xmlDoc.CreateElement(nsPrefix, "Radius", ns);
radiusElement.InnerText = edge.Trajectory.ActualRadius.ToString("F3", CultureInfo.InvariantCulture);
trajectoryElement.AppendChild(radiusElement);
// DeflectionAngle
var deflectionAngleElement = xmlDoc.CreateElement(nsPrefix, "DeflectionAngle", ns);
deflectionAngleElement.InnerText = edge.Trajectory.DeflectionAngle.ToString("F3", CultureInfo.InvariantCulture);
trajectoryElement.AppendChild(deflectionAngleElement);
edgeElement.AppendChild(trajectoryElement);
}
edgesElement.AppendChild(edgeElement);
}
}
// ObjectLimits (使用 -1 表示无限制)
var objectLimitsElement = xmlDoc.CreateElement(nsPrefix, "ObjectLimits", ns);
var maxLengthElement = xmlDoc.CreateElement(nsPrefix, "MaxLength", ns);
maxLengthElement.InnerText = (route.MaxObjectLength > 0 ? route.MaxObjectLength : -1).ToString("F3", CultureInfo.InvariantCulture);
objectLimitsElement.AppendChild(maxLengthElement);
var maxWidthElement = xmlDoc.CreateElement(nsPrefix, "MaxWidth", ns);
maxWidthElement.InnerText = (route.MaxObjectWidth > 0 ? route.MaxObjectWidth : -1).ToString("F3", CultureInfo.InvariantCulture);
objectLimitsElement.AppendChild(maxWidthElement);
var maxHeightElement = xmlDoc.CreateElement(nsPrefix, "MaxHeight", ns);
maxHeightElement.InnerText = (route.MaxObjectHeight > 0 ? route.MaxObjectHeight : -1).ToString("F3", CultureInfo.InvariantCulture);
objectLimitsElement.AppendChild(maxHeightElement);
var safetyMarginElement = xmlDoc.CreateElement(nsPrefix, "SafetyMargin", ns);
safetyMarginElement.InnerText = (route.SafetyMargin >= 0 ? route.SafetyMargin : 0.5).ToString("F3", CultureInfo.InvariantCulture);
objectLimitsElement.AppendChild(safetyMarginElement);
// MaxWeight (新增,默认 -1 表示无限制)
var maxWeightElement = xmlDoc.CreateElement(nsPrefix, "MaxWeight", ns);
maxWeightElement.InnerText = "-1";
objectLimitsElement.AppendChild(maxWeightElement);
pathOrderElement.AppendChild(objectLimitsElement);
// CoordinateSystem
var coordinateSystemElement = xmlDoc.CreateElement(nsPrefix, "CoordinateSystem", ns);
coordinateSystemElement.InnerText = settings?.CoordinateSystem ?? "Global";
pathOrderElement.AppendChild(coordinateSystemElement);
return pathOrderElement;
}
/// <summary>
/// 将PathPointType映射到DELMIA NodeType枚举
/// 支持吊装路径特殊节点类型LiftPoint, DescendPoint, HoverPoint
/// </summary>
private string MapToDelmiaNodeType(PathPointType type, PathType pathType = PathType.Ground, int pointIndex = 0, int totalPoints = 0)
{
// 基础类型映射
switch (type)
{
case PathPointType.StartPoint:
return "StartPoint";
case PathPointType.EndPoint:
return "EndPoint";
case PathPointType.WayPoint:
default:
// 对于吊装路径,根据点位置判断特殊类型
if (pathType == PathType.Hoisting && totalPoints > 2)
{
// 吊装路径的第二点通常是提升点
if (pointIndex == 1)
return "LiftPoint";
// 吊装路径的倒数第二点通常是下降点
if (pointIndex == totalPoints - 2)
return "DescendPoint";
// 中间空中点
if (pointIndex > 1 && pointIndex < totalPoints - 2)
return "HoverPoint";
}
return "WayPoint";
}
}
/// <summary>
/// 将PathType映射到DELMIA PathTypeEnum
/// </summary>
private string MapToDelmiaPathType(PathType pathType)
{
switch (pathType)
{
case PathType.Ground:
return "Ground";
case PathType.Rail:
case PathType.Hoisting:
return "Aerial";
default:
return "Mixed";
}
}
/// <summary>
/// 将PathSegmentType映射到DELMIA EdgeTypeEnum
/// 支持吊装路径特殊边类型vertical, suspension, hoisting
/// </summary>
private string MapToDelmiaEdgeType(PathSegmentType segmentType, PathType pathType = PathType.Ground)
{
switch (segmentType)
{
case PathSegmentType.Arc:
return "arc";
case PathSegmentType.Straight:
default:
// 对于吊装路径,根据上下文判断是否为垂直运动
if (pathType == PathType.Hoisting)
return "hoisting";
if (pathType == PathType.Rail)
return "suspension";
return "straight";
}
}
/// <summary>
/// 获取默认导出路径
/// </summary>
@ -1279,7 +1651,8 @@ namespace NavisworksTransport
Json,
Csv,
Delmia,
Navisworks
Navisworks,
DelmiaApriso
}
/// <summary>

View File

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:apr="http://www.dassaultsystemes.com/delmia/apriso"
targetNamespace="http://www.dassaultsystemes.com/delmia/apriso"
elementFormDefault="qualified">
<xs:element name="TransportPathOrders" type="apr:TransportPathOrdersType"/>
<xs:complexType name="TransportPathOrdersType">
<xs:sequence>
<xs:element name="PathOrder" type="apr:PathOrderType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PathOrderType">
<xs:sequence>
<xs:element name="OrderId" type="xs:string"/>
<xs:element name="OrderName" type="xs:string"/>
<xs:element name="Description" type="xs:string"/>
<xs:element name="PathType" type="apr:PathTypeEnum"/>
<xs:element name="TotalLength" type="xs:decimal"/>
<xs:element name="Timestamp" type="xs:dateTime"/>
<xs:element name="Generator" type="xs:string"/>
<xs:element name="Version" type="xs:string"/>
<xs:element name="Nodes" type="apr:NodesType"/>
<xs:element name="Edges" type="apr:EdgesType"/>
<xs:element name="ObjectLimits" type="apr:ObjectLimitsType"/>
<xs:element name="CoordinateSystem" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<!-- 路径类型枚举 -->
<xs:simpleType name="PathTypeEnum">
<xs:restriction base="xs:string">
<xs:enumeration value="Ground"/>
<xs:enumeration value="Aerial"/>
<xs:enumeration value="Underground"/>
<xs:enumeration value="Mixed"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="NodesType">
<xs:sequence>
<xs:element name="Node" type="apr:NodeType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="NodeType">
<xs:sequence>
<xs:element name="NodeId" type="xs:string"/>
<xs:element name="SequenceId" type="xs:int"/>
<xs:element name="NodeName" type="xs:string"/>
<xs:element name="NodeType" type="apr:NodeTypeEnum"/>
<xs:element name="Position" type="apr:PositionType"/>
<xs:element name="Released" type="xs:boolean"/>
<xs:element name="LiftHeight" type="xs:decimal" minOccurs="0"/>
<xs:element name="LoadCapacity" type="xs:decimal" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="NodeTypeEnum">
<xs:restriction base="xs:string">
<xs:enumeration value="StartPoint"/>
<xs:enumeration value="WayPoint"/>
<xs:enumeration value="EndPoint"/>
<xs:enumeration value="ChargePoint"/>
<xs:enumeration value="ParkPoint"/>
<xs:enumeration value="LiftPoint"/>
<xs:enumeration value="DescendPoint"/>
<xs:enumeration value="HoverPoint"/>
<xs:enumeration value="TransferPoint"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="PositionType">
<xs:sequence>
<xs:element name="X" type="xs:decimal"/>
<xs:element name="Y" type="xs:decimal"/>
<xs:element name="Z" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="EdgesType">
<xs:sequence>
<xs:element name="Edge" type="apr:EdgeType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="EdgeType">
<xs:sequence>
<xs:element name="EdgeId" type="xs:string"/>
<xs:element name="EdgeType" type="apr:EdgeTypeEnum"/>
<xs:element name="SequenceId" type="xs:int"/>
<xs:element name="StartNodeId" type="xs:string"/>
<xs:element name="EndNodeId" type="xs:string"/>
<xs:element name="PhysicalLength" type="xs:decimal"/>
<xs:element name="Trajectory" type="apr:TrajectoryType" minOccurs="0"/>
<xs:element name="MaxSpeed" type="xs:decimal" minOccurs="0"/>
<xs:element name="MaxAcceleration" type="xs:decimal" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="EdgeTypeEnum">
<xs:restriction base="xs:string">
<xs:enumeration value="straight"/>
<xs:enumeration value="arc"/>
<xs:enumeration value="bezier"/>
<xs:enumeration value="vertical"/>
<xs:enumeration value="suspension"/>
<xs:enumeration value="hoisting"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TrajectoryType">
<xs:sequence>
<xs:element name="StartTangent" type="apr:PositionType"/>
<xs:element name="EndTangent" type="apr:PositionType"/>
<xs:element name="ArcCenter" type="apr:PositionType" minOccurs="0"/>
<xs:element name="Radius" type="xs:decimal" minOccurs="0"/>
<xs:element name="DeflectionAngle" type="xs:decimal" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ObjectLimitsType">
<xs:sequence>
<xs:element name="MaxLength" type="xs:decimal"/>
<xs:element name="MaxWidth" type="xs:decimal"/>
<xs:element name="MaxHeight" type="xs:decimal"/>
<xs:element name="SafetyMargin" type="xs:decimal"/>
<xs:element name="MaxWeight" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

View File

@ -2977,7 +2977,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var saveFileDialog = new SaveFileDialog
{
Title = "导出全部路径",
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|CSV文件 (*.csv)|*.csv|所有文件 (*.*)|*.*",
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|CSV文件 (*.csv)|*.csv|DELMIA Apriso XML (*.aprxml)|*.aprxml|所有文件 (*.*)|*.*",
FilterIndex = 1,
FileName = $"路径导出_{DateTime.Now:yyyyMMdd_HHmmss}",
DefaultExt = "xml",
@ -2987,19 +2987,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (saveFileDialog.ShowDialog() == true)
{
var filePath = saveFileDialog.FileName;
var extension = Path.GetExtension(filePath).ToLower();
// 确定导出格式
// 确定导出格式通过FilterIndex判断因为DELMIA Apriso和普通XML都是.xml扩展名
ExportFormat exportFormat;
switch (extension)
switch (saveFileDialog.FilterIndex)
{
case ".json":
case 2: // JSON文件
exportFormat = ExportFormat.Json;
break;
case ".csv":
case 3: // CSV文件
exportFormat = ExportFormat.Csv;
break;
default:
case 4: // DELMIA Apriso XML
exportFormat = ExportFormat.DelmiaApriso;
break;
default: // XML文件或其他
exportFormat = ExportFormat.Xml;
break;
}
@ -3065,7 +3067,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
var saveFileDialog = new SaveFileDialog
{
Title = $"导出选中路径: {SelectedPathRoute?.Name}",
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|CSV文件 (*.csv)|*.csv|所有文件 (*.*)|*.*",
Filter = "XML文件 (*.xml)|*.xml|JSON文件 (*.json)|*.json|CSV文件 (*.csv)|*.csv|DELMIA Apriso XML (*.aprxml)|*.aprxml|所有文件 (*.*)|*.*",
FilterIndex = 1,
FileName = SelectedPathRoute?.Name?.Replace(" ", "_") ?? "路径",
DefaultExt = "xml",
@ -3075,19 +3077,21 @@ namespace NavisworksTransport.UI.WPF.ViewModels
if (saveFileDialog.ShowDialog() == true)
{
var filePath = saveFileDialog.FileName;
var extension = Path.GetExtension(filePath).ToLower();
// 确定导出格式
// 确定导出格式通过FilterIndex判断因为DELMIA Apriso和普通XML都是.xml扩展名
ExportFormat exportFormat;
switch (extension)
switch (saveFileDialog.FilterIndex)
{
case ".json":
case 2: // JSON文件
exportFormat = ExportFormat.Json;
break;
case ".csv":
case 3: // CSV文件
exportFormat = ExportFormat.Csv;
break;
default:
case 4: // DELMIA Apriso XML
exportFormat = ExportFormat.DelmiaApriso;
break;
default: // XML文件或其他
exportFormat = ExportFormat.Xml;
break;
}