XML blijft een hoeksteen van de uitwisseling van gezondheidszorggegevens, het versterken van HL7 boodschappen, bedrijfsintegratiemotoren en erfgoed ziekenhuisinformatiesystemen. Converteren van DICOM metadata naar XML maakt onbeperkt integratie tussen medische imaging systemen en een breder zorg IT-infrastructuur mogelijk. Deze gids toont hoe om te converteren in XML met behulp van Aspose.Medical voor .NET.

Waarom XML voor gezondheidszorg integratie?

Terwijl JSON de moderne web-API’s domineert, blijft XML van essentieel belang in de gezondheidszorg om verschillende redenen:

  • HL7 standaard: HL7 v2 en v3 berichten gebruiken XML-gebaseerde formaten uitgebreid
  • Enterprise integration: Veel gezondheidszorg integratiemotoren (Mirth Connect, Rhapsody) werken voornamelijk met XML
  • Legacy-systemen: geïnstalleerde ziekenhuisinformatie systemen vereisen vaak XML-datafeeds
  • Document Standards: CDA (Clinical Document Architecture) en andere klinische documenten gebruiken XML
  • Validatie: XML Schema (XSD) biedt robuste data validatiecapaciteiten

Basic DICOM naar XML Conversie

De eenvoudigste conversie van DICOM naar 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);
        }
    }
}

Geformateerde XML output

Voor menselijk leesbare productie en 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;
}

Round-Trip Conversie: XML naar DICOM

Convert XML terug naar DICOM voor bidirectionele werkstromen:

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}");
    }
}

Het bouwen van een HL7 Integration Bridge

Creëer een service die metadata van DICOM verandert in HL7-compatible XML:

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();
    }
}

Integratie met Healthcare Middleware

Creëren van een service voor ondernemingsintegratiemotoren:

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();
    }
}

Batchverwerking voor Enterprise Migration

Handelen van grootschalige DICOM naar XML conversie voor systeemmigraties:

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 voor XML Conversie

Creëren van web-endpoints voor on-demand conversie:

[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 Validatie met Schema

Valideer converteerde XML tegen een aangepaste schema:

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;
    }
}

Beste praktijken

Bij het omzetten van DICOM naar XML voor gezondheidszorg integratie:

  • Zorg voor codering: Zorg ervoor dat de karaktercodering correct wordt behandeld, vooral voor internationale patiëntennamen
  • Binaire gegevens handelen: Grote pixelgegevens moeten extern worden verwijderd in plaats van in XML geïntegreerd
  • Validate output: Gebruik XML schema validatie voor kritische integratiepunten
  • Consider prestaties: Voor grote bestanden, gebruik streaming serialisatie en parallelle verwerking
  • Document mapings: Behoud een duidelijke documentatie van hoe DICOM de kaart in uw XML-structuur geeft

Conclusie

Het omzetten van DICOM-bestanden naar XML maakt integratie mogelijk met bedrijfsgezondheidssystemen, HL7-berichten en erfgoedtoepassingen. Aspose.Medical voor .NET biedt robuste serialisatiecapaciteiten met ondersteuning voor rond-trip conversie, dat de integriteit van gegevens over formattransformaties garandeert. Of u nu integraatbronnen bouwt, gegevens migreert of verbindt met ziekenhuisinformatiesystems, deze XML-conversie technieken bieden een solide basis voor gezondheidszorg-interoperabiliteit.

Voor meer informatie over DICOM XML serialisatie, bezoek de Aspose.Medische documentatie.

More in this category