. NET XML найти и заменить узлы - PullRequest
0 голосов
/ 27 мая 2020

У меня есть старое приложение, разработанное на старой архитектуре, которое мне нужно перенести в современный мир; в старой архитектуре были особенности, которые я не могу воспроизвести. Идея такая: я поставщик данных. У клиентов будут особые требования к формату данных c. Чтобы облегчить это, клиенты создают «xml шаблоны документов», и с помощью этого механизма мое приложение заполняет данные в точном формате, который им нужен. Рассмотрим этот произвольный образец, предоставленный заказчиком xml:

<xml><data><people>
<replacetag1><person><name>$NAME$</name><address>$ADDRESS$</address></person></replacetag1>
</people></data></xml>

Этот документ читается, код находит <replacetag1>, берет содержимое внутри указанного тега и генерирует <person> или <person> s. Это оставляет полное форматирование документа на усмотрение клиента и его требований.

Приложение содержит следующую базовую функцию (vb. net, но могла бы реализовать ее аналогичным образом в c#):

Dim oDoc = XElement.Load(FileName)
For Each oDesc In oDoc.Descendants
    If oDesc.Name.LocalName.StartsWith(TagPrefix, StringComparison.OrdinalIgnoreCase) Then
        Dim sVal = String.Concat(oDesc.Nodes)
        RaiseEvent TagReplace(oDesc.Name.LocalName, sVal)
        oDesc.ReplaceWith(sVal)
    End If
Next

Вместо того, чтобы искать специально для тега <replacetag1>, код совпадает с началом имени тега (TagPrefix) в ожидании, что потребуется выполнить несколько замен по нескольким причинам, и все это RaiseEvent / ReplaceWith код работает точно так, как ожидалось, на первом проходе. Если я установил точку останова после oDes c .ReplaceWith, документ (oDo c) в этой точке будет выглядеть идеально.

Но в этот момент из-за изменения базового документа итератор сломается и Я получаю исключение NullReferenceException в «Далее». Из-за этой ошибки я не смог поймать второе появление другого <replacetag1> (редко, но возможно) или другого типа замены (ie <replacetag2>) в том же документе. Мне нужно продолжить итерацию остальной части документа, ища больше замен, и нужно, чтобы он был sh изящно.

Это использует Xml .Linq, но DOM может быть лучше для обработки таких типов на - доработка документа «на лету»; Я в лучшем случае новичок в обеих технологиях.

Изменить: Чтобы обрабатывать заменяемые теги, которые выходят из самого контента (а также из-за исходной проблемы), я решил перепроектировать это, чтобы выполнять рекурсивное сканирование и замену внутри самой рекурсивной подпрограммы. Затем весь документ повторно сканируется с самого начала каждый раз, но у него есть возможность обрабатывать заменяющие теги внутри заменяющего содержимого, и он может просто выполнить Exit For, прежде чем возникнет оскорбительная ошибка:

Dim oDoc = XElement.Load(FileName)
CheckReplacements(oDoc)
Private Sub CheckReplacements(XE As XElement)
    For Each oDesc In XE.Descendants
        If oDesc.Name.LocalName.StartsWith(TagPrefix, StringComparison.OrdinalIgnoreCase) Then
            Dim sVal = String.Concat(oDesc.Nodes)
            RaiseEvent TagReplace(oDesc.Name.LocalName, sVal)
            oDesc.ReplaceWith(XElement.Parse(sVal))
            CheckReplacements(XE)
            Exit For
        End If
    Next
End Sub

Этот метод отлично работает и буду работать над моим решением. Однако, если разметка не помещается в элемент, в который нужно заключить вывод, это не сработает с исключением XmlException в XElement.Parse(). Любые предложения о том, как лучше обрабатывать sVal, являющийся либо текстом, либо фрагментом xml, чем также обрабатывать кодировку, как я ожидал?

1 Ответ

1 голос
/ 27 мая 2020

Это может вам не понравиться, но я бы сделал это, взяв ваш «xml шаблон документа» и преобразовав его в таблицу стилей XSLT (конечно, используя XSLT для преобразования). Затем вам нужно только применить сгенерированную таблицу стилей; не требуется низкоуровневое кодирование C# или LINQ.

Преимущество этого подхода состоит в том, что после его запуска вы не ограничены использованием таблиц стилей, созданных с помощью этого механизма; вы также можете разрешить потребителям данных напрямую предоставлять свой собственный код XSLT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...