XML ยังคงเป็นมุมของการแลกเปลี่ยนข้อมูลทางการแพทย์ช่วยให้การสื่อสาร HL7 มอเตอร์การบูรณาการขององค์กรและระบบข้อมูลโรงพยาบาลที่ได้รับอนุญาโตตุลาการ การแปลง metadata ของ DICOM ไปยัง XML ช่วยให้มีการรวมกันอย่างต่อเนื่องระหว่างระบบภาพทางแพทย์และโครงสร้างพื้นฐาน IT การดูแลสุขภาพที่กว้างขึ้น คู่มือนี้แสดงให้เห็นถึงวิธีการแปลง DIKOM เป็น XML โดยใช้ Aspose.Medical สําหรับ .NET

ทําไม XML สําหรับการรวมการดูแลสุขภาพ?

ในขณะที่ JSON มุ่งเน้นไปที่ APIs เว็บสมัยใหม่ XML ยังคงเป็นสิ่งสําคัญในการดูแลสุขภาพสําหรับเหตุผลหลายอย่าง:

  • HL7 มาตรฐาน: HL7 v2 และ v3 โพสต์ใช้รูปแบบ XML โดยกว้างขวาง
  • การบูรณาการองค์กร: มอเตอร์การรวมการดูแลสุขภาพจํานวนมาก (Mirth Connect, Rhapsody) ส่วนใหญ่ทํางานกับ XML
  • Legacy ระบบ: ระบบข้อมูลโรงพยาบาลที่ตั้งขึ้นมักจําเป็นต้องมีข้อมูล XML
  • มาตรฐานเอกสาร: CDA (Architecture of Clinical Document) และข้อมูลคลินิกอื่น ๆ ใช้ XML
  • ** Validation**: XML Schema (XSD) ให้ความสามารถในการยืนยันข้อมูลที่มั่นคง

ฐาน DICOM ไปยัง XML การแปลง

การแปลงจาก DICOM ไปยัง XML ที่ง่ายที่สุด:

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Serialization;

public class DicomXmlConverter
{
    public string ConvertToXml(string dicomFilePath)
    {
        // Load DICOM file
        DicomFile dicomFile = DicomFile.Open(dicomFilePath);
        
        // Serialize to XML string
        string xml = DicomXmlSerializer.Serialize(dicomFile.Dataset);
        
        return xml;
    }
    
    public void ConvertToXmlFile(string dicomFilePath, string outputXmlPath)
    {
        DicomFile dicomFile = DicomFile.Open(dicomFilePath);
        
        using (var stream = new FileStream(outputXmlPath, FileMode.Create))
        {
            DicomXmlSerializer.Serialize(stream, dicomFile.Dataset);
        }
    }
}

รูปแบบ XML Output

สําหรับการผลิตที่สามารถอ่านได้จากมนุษย์และ Debugging:

public string ConvertToFormattedXml(string dicomFilePath)
{
    DicomFile dicomFile = DicomFile.Open(dicomFilePath);
    
    var options = new DicomXmlSerializerOptions
    {
        WriteIndented = true  // Pretty-print XML
    };
    
    string xml = DicomXmlSerializer.Serialize(dicomFile.Dataset, options);
    
    return xml;
}

การแปลงเส้นรอบ: XML ไปยัง DICOM

แปลง XML กลับไปยัง DICOM สําหรับการไหลของงานสองทิศทาง:

public class DicomXmlRoundTrip
{
    public void XmlToDicom(string xmlFilePath, string outputDicomPath)
    {
        // Read XML content
        string xml = File.ReadAllText(xmlFilePath);
        
        // Deserialize to DICOM dataset
        DicomDataset dataset = DicomXmlSerializer.Deserialize(xml);
        
        // Create DICOM file and save
        DicomFile dicomFile = new DicomFile(dataset);
        dicomFile.Save(outputDicomPath);
    }
    
    public DicomDataset XmlStringToDataset(string xml)
    {
        return DicomXmlSerializer.Deserialize(xml);
    }
    
    public void ValidateRoundTrip(string originalDicomPath)
    {
        // Load original
        DicomFile original = DicomFile.Open(originalDicomPath);
        
        // Convert to XML
        string xml = DicomXmlSerializer.Serialize(original.Dataset);
        
        // Convert back to DICOM
        DicomDataset restored = DicomXmlSerializer.Deserialize(xml);
        
        // Compare key fields
        string originalPatientName = original.Dataset.GetString(DicomTag.PatientName);
        string restoredPatientName = restored.GetString(DicomTag.PatientName);
        
        Console.WriteLine($"Original Patient Name: {originalPatientName}");
        Console.WriteLine($"Restored Patient Name: {restoredPatientName}");
        Console.WriteLine($"Match: {originalPatientName == restoredPatientName}");
    }
}

สร้างสะพานการรวม HL7

สร้างบริการที่แปลง DICOM metadata เป็น XML ที่เข้ากันได้ HL7:

using System.Xml.Linq;

public class DicomHl7Bridge
{
    public string ConvertToHl7CompatibleXml(string dicomFilePath)
    {
        DicomFile dicomFile = DicomFile.Open(dicomFilePath);
        var dataset = dicomFile.Dataset;
        
        // Create HL7-style XML structure
        var hl7Message = new XElement("ORU_R01",
            new XAttribute("xmlns", "urn:hl7-org:v2xml"),
            
            // Message Header
            new XElement("MSH",
                new XElement("MSH.1", "|"),
                new XElement("MSH.2", "^~\\&"),
                new XElement("MSH.3", "PACS"),
                new XElement("MSH.4", dataset.GetString(DicomTag.InstitutionName) ?? ""),
                new XElement("MSH.7", DateTime.Now.ToString("yyyyMMddHHmmss")),
                new XElement("MSH.9",
                    new XElement("MSG.1", "ORU"),
                    new XElement("MSG.2", "R01")),
                new XElement("MSH.10", Guid.NewGuid().ToString()),
                new XElement("MSH.11", "P"),
                new XElement("MSH.12", "2.5.1")
            ),
            
            // Patient Identification
            new XElement("PID",
                new XElement("PID.3",
                    new XElement("CX.1", dataset.GetString(DicomTag.PatientID) ?? "")),
                new XElement("PID.5",
                    new XElement("XPN.1", dataset.GetString(DicomTag.PatientName) ?? "")),
                new XElement("PID.7", dataset.GetString(DicomTag.PatientBirthDate) ?? ""),
                new XElement("PID.8", dataset.GetString(DicomTag.PatientSex) ?? "")
            ),
            
            // Order Information
            new XElement("OBR",
                new XElement("OBR.2", dataset.GetString(DicomTag.AccessionNumber) ?? ""),
                new XElement("OBR.4",
                    new XElement("CE.1", dataset.GetString(DicomTag.Modality) ?? ""),
                    new XElement("CE.2", dataset.GetString(DicomTag.StudyDescription) ?? "")),
                new XElement("OBR.7", dataset.GetString(DicomTag.StudyDate) ?? ""),
                new XElement("OBR.24", "RAD")
            ),
            
            // Observation with DICOM reference
            new XElement("OBX",
                new XElement("OBX.2", "RP"),
                new XElement("OBX.3",
                    new XElement("CE.1", "DICOM"),
                    new XElement("CE.2", "DICOM Study")),
                new XElement("OBX.5", dataset.GetString(DicomTag.StudyInstanceUID) ?? ""),
                new XElement("OBX.11", "F")
            )
        );
        
        return hl7Message.ToString();
    }
}

การบูรณาการกับ Healthcare Middleware

สร้างบริการสําหรับเครื่องยนต์บูรณาการองค์กร:

public class HealthcareIntegrationService
{
    private readonly string _outputDirectory;
    private readonly ILogger _logger;

    public HealthcareIntegrationService(string outputDirectory, ILogger logger)
    {
        _outputDirectory = outputDirectory;
        _logger = logger;
    }

    public async Task ProcessDicomForIntegration(string dicomFilePath)
    {
        try
        {
            DicomFile dicomFile = DicomFile.Open(dicomFilePath);
            var dataset = dicomFile.Dataset;
            
            string accessionNumber = dataset.GetString(DicomTag.AccessionNumber) ?? 
                                     Guid.NewGuid().ToString();
            
            // Generate standard DICOM XML
            string dicomXml = DicomXmlSerializer.Serialize(dataset, 
                new DicomXmlSerializerOptions { WriteIndented = true });
            
            // Save DICOM XML
            string dicomXmlPath = Path.Combine(_outputDirectory, $"{accessionNumber}_dicom.xml");
            await File.WriteAllTextAsync(dicomXmlPath, dicomXml);
            
            // Generate HL7 bridge XML
            var bridge = new DicomHl7Bridge();
            string hl7Xml = bridge.ConvertToHl7CompatibleXml(dicomFilePath);
            
            string hl7XmlPath = Path.Combine(_outputDirectory, $"{accessionNumber}_hl7.xml");
            await File.WriteAllTextAsync(hl7XmlPath, hl7Xml);
            
            // Generate metadata summary for quick lookup
            var summary = GenerateMetadataSummary(dataset, accessionNumber);
            string summaryPath = Path.Combine(_outputDirectory, $"{accessionNumber}_summary.xml");
            await File.WriteAllTextAsync(summaryPath, summary);
            
            _logger.LogInformation($"Processed DICOM file: {accessionNumber}");
        }
        catch (Exception ex)
        {
            _logger.LogError($"Failed to process {dicomFilePath}: {ex.Message}");
            throw;
        }
    }

    private string GenerateMetadataSummary(DicomDataset dataset, string accessionNumber)
    {
        var summary = new XElement("DicomMetadataSummary",
            new XAttribute("timestamp", DateTime.UtcNow.ToString("O")),
            
            new XElement("Identifiers",
                new XElement("AccessionNumber", accessionNumber),
                new XElement("StudyInstanceUID", dataset.GetString(DicomTag.StudyInstanceUID)),
                new XElement("SeriesInstanceUID", dataset.GetString(DicomTag.SeriesInstanceUID)),
                new XElement("SOPInstanceUID", dataset.GetString(DicomTag.SOPInstanceUID))
            ),
            
            new XElement("Patient",
                new XElement("ID", dataset.GetString(DicomTag.PatientID)),
                new XElement("Name", dataset.GetString(DicomTag.PatientName)),
                new XElement("BirthDate", dataset.GetString(DicomTag.PatientBirthDate)),
                new XElement("Sex", dataset.GetString(DicomTag.PatientSex))
            ),
            
            new XElement("Study",
                new XElement("Date", dataset.GetString(DicomTag.StudyDate)),
                new XElement("Time", dataset.GetString(DicomTag.StudyTime)),
                new XElement("Description", dataset.GetString(DicomTag.StudyDescription)),
                new XElement("ReferringPhysician", dataset.GetString(DicomTag.ReferringPhysicianName))
            ),
            
            new XElement("Series",
                new XElement("Modality", dataset.GetString(DicomTag.Modality)),
                new XElement("Description", dataset.GetString(DicomTag.SeriesDescription)),
                new XElement("BodyPart", dataset.GetString(DicomTag.BodyPartExamined))
            ),
            
            new XElement("Equipment",
                new XElement("Manufacturer", dataset.GetString(DicomTag.Manufacturer)),
                new XElement("Model", dataset.GetString(DicomTag.ManufacturerModelName)),
                new XElement("StationName", dataset.GetString(DicomTag.StationName)),
                new XElement("Institution", dataset.GetString(DicomTag.InstitutionName))
            )
        );
        
        return summary.ToString();
    }
}

การประมวลผล Batch สําหรับการย้ายธุรกิจ

การจัดการการแปลงขนาดใหญ่ DICOM ไปยัง XML สําหรับการย้ายระบบ:

public class EnterpriseMigrationService
{
    public async Task MigrateDicomArchiveToXml(
        string sourceDirectory,
        string targetDirectory,
        int maxParallelism = 4)
    {
        Directory.CreateDirectory(targetDirectory);
        
        var dicomFiles = Directory.GetFiles(sourceDirectory, "*.dcm", SearchOption.AllDirectories);
        
        var semaphore = new SemaphoreSlim(maxParallelism);
        var tasks = new List<Task>();
        var progress = 0;
        var total = dicomFiles.Length;

        foreach (var filePath in dicomFiles)
        {
            await semaphore.WaitAsync();
            
            tasks.Add(Task.Run(async () =>
            {
                try
                {
                    await ConvertSingleFile(filePath, sourceDirectory, targetDirectory);
                    
                    var current = Interlocked.Increment(ref progress);
                    if (current % 100 == 0)
                    {
                        Console.WriteLine($"Progress: {current}/{total} files processed");
                    }
                }
                finally
                {
                    semaphore.Release();
                }
            }));
        }

        await Task.WhenAll(tasks);
        
        Console.WriteLine($"Migration complete: {total} files processed");
    }

    private async Task ConvertSingleFile(
        string sourcePath, 
        string sourceRoot, 
        string targetRoot)
    {
        try
        {
            DicomFile dicomFile = DicomFile.Open(sourcePath);
            
            // Preserve directory structure
            string relativePath = Path.GetRelativePath(sourceRoot, sourcePath);
            string targetPath = Path.Combine(targetRoot, 
                Path.ChangeExtension(relativePath, ".xml"));
            
            Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
            
            var options = new DicomXmlSerializerOptions { WriteIndented = true };
            
            using (var stream = new FileStream(targetPath, FileMode.Create))
            {
                DicomXmlSerializer.Serialize(stream, dicomFile.Dataset, options);
            }
        }
        catch (Exception ex)
        {
            // Log error but continue processing
            await File.AppendAllTextAsync(
                Path.Combine(targetRoot, "errors.log"),
                $"{DateTime.Now}: {sourcePath} - {ex.Message}\n");
        }
    }
}

ASP.NET Core API สําหรับการแปลง XML

สร้างจุดสิ้นสุดเว็บสําหรับการแปลง on-demand:

[ApiController]
[Route("api/[controller]")]
public class DicomXmlController : ControllerBase
{
    [HttpPost("convert")]
    [Produces("application/xml")]
    public async Task<IActionResult> ConvertToXml(IFormFile file)
    {
        if (file == null || file.Length == 0)
        {
            return BadRequest("No DICOM file provided");
        }

        var tempPath = Path.GetTempFileName();
        try
        {
            using (var stream = new FileStream(tempPath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }

            DicomFile dicomFile = DicomFile.Open(tempPath);
            
            var options = new DicomXmlSerializerOptions { WriteIndented = true };
            string xml = DicomXmlSerializer.Serialize(dicomFile.Dataset, options);

            return Content(xml, "application/xml");
        }
        finally
        {
            System.IO.File.Delete(tempPath);
        }
    }

    [HttpPost("to-hl7")]
    [Produces("application/xml")]
    public async Task<IActionResult> ConvertToHl7(IFormFile file)
    {
        if (file == null || file.Length == 0)
        {
            return BadRequest("No DICOM file provided");
        }

        var tempPath = Path.GetTempFileName();
        try
        {
            using (var stream = new FileStream(tempPath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }

            var bridge = new DicomHl7Bridge();
            string hl7Xml = bridge.ConvertToHl7CompatibleXml(tempPath);

            return Content(hl7Xml, "application/xml");
        }
        finally
        {
            System.IO.File.Delete(tempPath);
        }
    }

    [HttpPost("from-xml")]
    public async Task<IActionResult> ConvertFromXml()
    {
        using var reader = new StreamReader(Request.Body);
        string xml = await reader.ReadToEndAsync();

        try
        {
            DicomDataset dataset = DicomXmlSerializer.Deserialize(xml);
            DicomFile dicomFile = new DicomFile(dataset);

            var memoryStream = new MemoryStream();
            dicomFile.Save(memoryStream);
            memoryStream.Position = 0;

            return File(memoryStream, "application/dicom", "converted.dcm");
        }
        catch (Exception ex)
        {
            return BadRequest($"Invalid XML: {ex.Message}");
        }
    }
}

การรับรอง XML ด้วย Schema

validate แปลง XML กับแผนที่กําหนดเอง:

using System.Xml;
using System.Xml.Schema;

public class DicomXmlValidator
{
    private readonly XmlSchemaSet _schemaSet;
    private readonly List<string> _validationErrors;

    public DicomXmlValidator(string schemaPath)
    {
        _schemaSet = new XmlSchemaSet();
        _schemaSet.Add(null, schemaPath);
        _validationErrors = new List<string>();
    }

    public bool ValidateXml(string xml, out List<string> errors)
    {
        _validationErrors.Clear();
        
        var settings = new XmlReaderSettings
        {
            ValidationType = ValidationType.Schema,
            Schemas = _schemaSet
        };
        
        settings.ValidationEventHandler += (sender, e) =>
        {
            _validationErrors.Add($"{e.Severity}: {e.Message}");
        };

        try
        {
            using (var stringReader = new StringReader(xml))
            using (var xmlReader = XmlReader.Create(stringReader, settings))
            {
                while (xmlReader.Read()) { }
            }
        }
        catch (XmlException ex)
        {
            _validationErrors.Add($"XML Error: {ex.Message}");
        }

        errors = new List<string>(_validationErrors);
        return errors.Count == 0;
    }
}

แนวทางที่ดีที่สุด

เมื่อแปลง DICOM ไปยัง XML สําหรับการรวมการดูแลสุขภาพ:

  • เก็บรหัส: ให้แน่ใจว่าการเข้ารหัสตัวละครได้รับการจัดการอย่างถูกต้องโดยเฉพาะอย่างยิ่งสําหรับชื่อผู้ป่วยระหว่างประเทศ
  • การประมวลผลข้อมูลไบนารี: ข้อมูล pixel ขนาดใหญ่ควรนํามาใช้ภายนอกแทนที่จะรวมไว้ใน XML
  • การตรวจสอบผลผลิต: ใช้การยืนยัน schema XML สําหรับจุดการรวมที่สําคัญ
  • ประสิทธิภาพการพิจารณา: สําหรับไฟล์ขนาดใหญ่ใช้การจัดเรียงแบบสตรีมมิ่งและการประมวลผลแบบคู่มือ
  • การ์ตูนเอกสาร: รักษาข้อมูลที่ชัดเจนเกี่ยวกับวิธีที่ DICOM แท็กแผนที่กับโครงสร้าง XML ของคุณ

ข้อสรุป

การแปลงไฟล์ DICOM ไปยัง XML ช่วยให้การบูรณาการกับระบบการดูแลสุขภาพขององค์กรการสื่อสาร HL7 และแอพพลิเคชันที่ได้รับอนุญาโตตุลาการ Aspose.Medical สําหรับ .NET ให้ความสามารถในการจัดอันดับที่แข็งแกร่งพร้อมการสนับสนุนการแปลงรอบ ๆ การรับประกันความสมบูรณ์ของข้อมูลผ่านการเปลี่ยนแปลงแบบฟอร์ม ไม่ว่าคุณจะสร้างสะพานการรวมข้อมูลการถ่ายโอนข้อมูลหรือเชื่อมต่อไปยังระบบข้อมูลในโรงพยาบาลเทคนิคการเปลี่ยน XML นี้ให้พื้นฐานที่มั่นคงสําหรับการทํางานร่วมกันด้านสุขภาพ

สําหรับข้อมูลเพิ่มเติมเกี่ยวกับ DICOM XML serialization, visit the Aspose.เอกสารทางการแพทย์.

More in this category