Я работаю с xml, который мне нужно скопировать и обновить, чтобы передать его для дальнейшей обработки. Проблема, с которой я сталкиваюсь, заключается в том, что я не нашел эффективного метода для этого. По сути, я хочу обновить некоторые данные, условно, а затем скопировать все узлы, которые не были обновлены. Почему это сложно, связано с объемом и дисперсией числа и имени узлов, которые нужно скопировать. Я также хочу НЕ копировать узлы, которые не имеют текстового значения. Ниже приведен пример:выборочно копировать и обновлять узлы xml с помощью XSLT
ВХОД XML-
<root>
<PersonProfile xmlns:'namespace'>
<ID>0001</ID>
<Name>
<FirstName>Jonathan</FirstName>
<PreferredName>John</PreferredName>
<MiddleName>A</MiddleName>
<LastName>Doe</LastName>
</Name>
<Country>US</Country>
<Biirthdate>01-01-1980</Birthdate>
<BirthPlace>
<City>Townsville</City>
<State>OR</State>
<Country>US</Country>
</Birthplace>
<Gender>Male</Gender>
<HomeState>OR</HomeState>
...
<nodeN>text</nodeN>
</PersonProfile>
</root>
Узел «PersonProfile» является лишь одним из нескольких наборов узлов внутри элемента «корень», каждый со своим собственным подмножеством данных. Такие, как почтовый адрес, контактная информация о чрезвычайных ситуациях и т. Д. То, что я пытаюсь сделать, это обновить узлы, если переменная имеет новое значение для них, а затем скопировать все узлы, которые не были обновлены.
Вот мой текущий XSLT
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:variable name='updateData' select='document("report")'/>
<!-- Identity Transform -->
<xsl:template match='@* | node()'>
<xsl:if test'. != ""'>
<xsl:copy>
<xsl:apply-templates select='@* | node()'/>
</xsl:copy>
</xsl:if>
</xsl:template>
<!-- Template to update Person Profile -->
<xsl:template match='PersonProfile'>
<xsl:copy>
<xsl:apply-templates select='*'/>
<xsl:element name='Name'>
<xsl:if test='exists($updateData/Preferred)'>
<xsl:element name='FirstName'>
<xsl:value-of select='$reportData/FirstName'/>
</xsl:element>
</xsl:if>
<xsl:if test='exists($updateData/Preferred)'>
<xsl:element name='PreferredName'>
<xsl:value-of select='$updateData/Preferred'/>
</xsl:element>
</xsl:if>
<xsl:if test='exists($updateData/Middle)'>
<xsl:element name='MiddleName'>
<xsl:value-of select='$updateData/Middle'/>
</xsl:element>
</xsl:if>
<xsl:if test='exists($updateData/LastName)'>
<xsl:element name='LastName'>
<xsl:value-of select='$updateData/wd:LastName'/>
</xsl:element>
</xsl:if>
</xsl:element>
<xsl:if test='exists($updateData/Country)'>
<xsl:element name='Country'>
<xsl:value-of select='$updateData/Country'/>
</xsl:element>
</xsl:if>
....
<!-- follows same structure until end of template -->
</xsl:copy>
</xsl:template>
<!-- More Templates to Update other Node sets -->
</xsl:stylesheet>
Что сейчас происходит, является то, что это копирование всех узлов, а затем добавить значения обновлений. Использование Saxon-PE 9.3.0.5, я получаю результат, похожий на этот:
Пример вывода
<root>
<PersonProfile xmlns:'namespace'>
<ID>0001</ID>
<Name>
<FirstName>Jonathan</FirstName>
<PreferredName>John</PreferredName>
<MiddleName>A</MiddleName>
<LastName>Doe</LastName>
</Name>
<Country>US</Country>
<Biirthdate>01-01-1980</Birthdate>
<BirthPlace>
<City>Townsville</City>
<State>OR</State>
<Country>US</Country>
</Birthplace>
<Gender>Male</Gender>
<HomeState>OR</HomeState>
...
<nodeN>text</nodeN>
<PreferredName>Jonathan</PreferredName>
<HomeState>WA</HomeState>
</PersonProfile>
</root>
Я понимаю, что это происходит потому, что я подаю шаблоны ко всем узлам в PersonProfile и что я могу указать, какие узлы исключить, но я чувствую, что это очень плохое решение, поскольку объем узлов может превышать 30 или более, и для этого потребуется письменное значение для каждого из них. Я верю, что XML имеет более элегантное решение, чем явное перечисление каждого из этих узлов. Я хотел бы иметь такой:
Желаемая Выход
<root>
<PersonProfile xmlns:'namespace'>
<ID>0001</ID>
<Name>
<FirstName>Jonathan</FirstName>
<PreferredName>Jonathan</PreferredName>
<MiddleName>A</MiddleName>
<LastName>Doe</LastName>
</Name>
<Country>US</Country>
<Biirthdate>01-01-1980</Birthdate>
<BirthPlace>
<City>Townsville</City>
<State>OR</State>
<Country>US</Country>
</Birthplace>
<Gender>Male</Gender>
<HomeState>WA</HomeState>
...
<nodeN>text</nodeN>
</PersonProfile>
</root>
Если кто-то может помочь мне создать структуру шаблона, который будет работать для структуры XML, я бы очень признателен. Он должен быть «повторно использован», поскольку существуют аналогичные структуры узлов, такие как профиль лица, к которому я должен был бы применить его, но с разными именами узлов и количеством элементов и т. Д.
Заранее за любую помощь!
- J
Итак, я нашел потенциальное решение, по сути, я создаю шаблон для каждого xpath, который можно обновить, а затем применить, - который работает достаточно хорошо. У меня только 1 проблема - как использовать шаблон, когда путь не существует! Допустим, что человеку не хватает Home State - я не могу это сделать, так как я могу сказать шаблону о создании нового узла? Спасибо! –