2015-05-25 2 views
1

Это на самом деле следующий вопрос к моему предыдущему, но я повторил свою проблему, поэтому, возможно, это проще решить. У меня есть данные XML в следующем формате:Слияние полей XML с XSLT

<v1:publications xmlns:commons="v3.commons.pure.atira.dk" 
      xmlns:v1="v1.publication-import.base-uk.pure.atira.dk"> 
<v1:book id="1" subType="book"> 
    <v1:peerReviewed>true</v1:peerReviewed> 
    <v1:publicationCategory>scientific</v1:publicationCategory> 
    <v1:publicationStatus>published</v1:publicationStatus> 
    <v1:language>fi</v1:language> 
    <v1:title> 
     <commons:text>Introduction to scientific reduction</commons:text> 
    </v1:title> 
    <v1:abstract/> 
    <v1:persons> 
     <v1:author> 
      <v1:role>author</v1:role> 
      <v1:person> 
       <v1:firstName>Jane</v1:firstName> 
       <v1:lastName>Smith</v1:lastName> 
      </v1:person> 
     </v1:author> 
    </v1:persons> 
    <v1:organisations> 
     <v1:organisation id="2250500"/> 
    </v1:organisations> 
    <v1:owner id="2250500"/> 
    <v1:publicationDate> 
    <commons:year>2013</commons:year> 
    </v1:publicationDate> 
    <v1:visibility>Public</v1:visibility> 
    <v1:numberOfPages>2</v1:numberOfPages> 
</v1:book> 
<v1:book id="1" subType="book"> 
    <v1:persons> 
     <v1:author> 
      <v1:role>author</v1:role> 
      <v1:person> 
       <v1:firstName>John</v1:firstName> 
       <v1:lastName>Doe</v1:lastName> 
      </v1:person> 
     </v1:author> 
    </v1:persons> 
    <v1:organisations> 
     <v1:organisation id="220300"/> 
    </v1:organisations> 
    </v1:book> 
</publications> 

XSLT Я до сих пор это:

<?xml version="1.0"?> 
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:commons="v3.commons.pure.atira.dk" 
xmlns:v1="v1.publication-import.base-uk.pure.atira.dk" 
exclude-result-prefixes="xsi xs" 
version="2.0"> 

<xsl:output method="xml" indent="yes" /> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/"> 
<v1:publications> 
    <xsl:for-each-group select="/v1:publications/v1:book" group-by="@id"> 
    <xsl:for-each-group select="current-group()" group-by="if(@Key) then @Key else 'no key'"> 
    <v1:book> 
     <!-- Copy attributes off the *first* GroupData element in the group --> 
     <xsl:copy-of select="current-group()[1]/@*"/> 

     <!-- Copy ItemData children from *all* GroupData elements in the group --> 

     <xsl:copy-of select="current-group()/*" /> 

     </v1:book> 
    </xsl:for-each-group> 
    </xsl:for-each-group> 
</v1:publications> 

Проблема заключается в том, что он создает отдельные узлы под <v1:book> дубликатов (v1 : лица), когда я хотел бы их комбинировать следующим образом:

<v1:persons> 
    <v1:author></v1:author> 
    <v1:author></v1:author> 
</v1:persons> 

Поля, подобные <v1:title/> Я мог бы легко удалить из XML заранее, чтобы они не были проблемой.

Желаемый результат должен быть следующим: я отредактировал несколько полей (идентификатор организации и идентификатор владельца, чтобы исправить их). Это фактические данные, которые импортируются правильно.

<?xml version="1.0" encoding="UTF-8"?> 
<v1:publications xmlns:commons="v3.commons.pure.atira.dk" 
      xmlns:v1="v1.publication-import.base-uk.pure.atira.dk"> 
<v1:book id="1" subType="book"> 
    <v1:peerReviewed>true</v1:peerReviewed> 
    <v1:publicationCategory>scientific</v1:publicationCategory> 
    <v1:publicationStatus>published</v1:publicationStatus> 
    <v1:language>fi_FI</v1:language> 
    <v1:title> 
     <commons:text>Introduction to scientific reduction</commons:text> 
    </v1:title> 
    <v1:persons> 
     <v1:author> 
      <v1:role>author</v1:role> 
      <v1:person> 
       <v1:firstName>Jane</v1:firstName> 
       <v1:lastName>Smith</v1:lastName> 
      </v1:person> 
     </v1:author> 
     <v1:author> 
      <v1:role>author</v1:role> 
      <v1:person> 
       <v1:firstName>John</v1:firstName> 
       <v1:lastName>Die</v1:lastName> 
      </v1:person> 
     </v1:author> 
    </v1:persons> 
    <v1:organisations> 
     <v1:organisation id="2250500"/> 
     <v1:organisation id="2250300"/> 
    </v1:organisations> 
    <v1:owner id="2250300"/> 
    <v1:publicationDate> 
    <commons:year>2013</commons:year> 
    </v1:publicationDate> 
    <v1:visibility>Public</v1:visibility> 
    <v1:numberOfPages>2</v1:numberOfPages> 
</v1:book> 
</v1:publications> 
+0

Можете ли вы вставить фактическое значение (ы), которое вы хотите, в желаемый результат? Как бы то ни было, неясно, какие данные вы хотите там (хотя мы можем догадаться). (Незначительное примечание: нет необходимости добавлять «Обновление: ..». Редактирование вопроса должно оставить вопрос «автономным».) (Также для вашего образца XML и XSLT нужны несколько закрывающих элементов.) – usr2564301

+0

@Jongware Спасибо за вход. Я добавил фактические желаемые данные выше. Он корректно проверяется при импорте. –

ответ

0

Предполагая, что желаемый результат является

<v1:persons> 
    <v1:author> 
     <v1:fullName>John Doe</v1:fullName> 
    </v1:author> 
</v1:persons> 

вам нужно заменить <xsl:copy-of>, что делает идеальную копию (и поэтому не допускает изменения в пределах), с шаблоном копирования каждого элемента.

Общая идентичность шаблон match="@*|node() будет соответствовать всем (см https://stackoverflow.com/a/617611/2564301), но это будет переопределен конкретного шаблона для match="v1:author". Это просто выписывает значения <v1:firstName> и <v1:lastName> с одним промежутком между ними.

Для согласования я добавил <xsl:copy>, чтобы скопировать сам тег <v1:author>, а также <xsl:apply-templates select="@*"/>, чтобы скопировать все его атрибуты. Таким образом, он также будет работать с таким элементом, как

<v1:author id='1'> 

- атрибут будет скопирован так, как ожидалось.

<xsl:template match="/"> 
<v1:publications> 
    <xsl:for-each-group select="/v1:publications/v1:book" group-by="@id"> 
    <xsl:for-each-group select="current-group()" group-by="if(@Key) then @Key else 'no key'"> 
    <v1:book> 
     <!-- Copy attributes off the *first* GroupData element in the group --> 
     <xsl:apply-templates select="current-group()[1]/@*"/> 

     <!-- Copy ItemData children from *all* GroupData elements in the group --> 
     <xsl:apply-templates select="current-group()/*" /> 

     </v1:book> 
    </xsl:for-each-group> 
    </xsl:for-each-group> 
</v1:publications> 
</xsl:template> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="v1:author"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <v1:fullName> 
      <xsl:value-of select="v1:person/v1:firstName" /> 
      <xsl:text> </xsl:text> 
      <xsl:value-of select="v1:person/v1:lastName" /> 
     </v1:fullName> 
    </xsl:copy> 
</xsl:template> 

Это делает точную копию входа, но с секцией <v1:persons> заменены

<v1:persons> 
    <v1:author id="1"> 
     <v1:fullName>Jane Smith</v1:fullName> 
    </v1:author> 
    <v1:author id="2"> 
     <v1:fullName>Bob Sandurz</v1:fullName> 
    </v1:author> 
    </v1:persons> 

(я добавил второе имя и атрибуты для тестирования.)

+0

Чем вы, многое узнали из своего примера. Но для меня проблема в том, что то, что я получаю: \t \t \t Джейн Смит \t \t И отдельный \t \t \t GBOB Sandurz \t \t Когда мне нужен Jane Smith Bob Sandurz

+0

@ AnthonyBerkins: ... '' в вашем вопросе не упоминалось. Но это простое решение: вы можете вставлять любые (соответствующие!) Набор тегов в любой момент вывода. – usr2564301

+0

Действительно я могу, и это поможет в будущем. Но проблема остается в том, что авторы идут под отдельными тегами , а не под тем же. –

0

Подобно тому, как другой подход, только копирование авторов книги с тем же id без конкатенации имени и фамилии - после XSLT

<?xml version="1.0"?> 
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:commons="v3.commons.pure.atira.dk" 
xmlns:v1="v1.publication-import.base-uk.pure.atira.dk" 
exclude-result-prefixes="xsi xs" 
version="2.0"> 
<xsl:output method="xml" indent="yes" /> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 
    <xsl:template match="/"> 
    <v1:publications> 
     <xsl:for-each-group select="/v1:publications/v1:book" group-by="@id"> 
     <xsl:apply-templates select="."/> 
     </xsl:for-each-group> 
    </v1:publications> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="v1:person"> 
    <xsl:variable name="id" select="ancestor::v1:book/@id"/> 
    <xsl:copy-of select="//v1:person[ancestor::v1:book[@id=$id]]"/> 
    </xsl:template> 
</xsl:stylesheet> 

применительно к вашей входной XML производит вывод (соответствующая часть)

<v1:persons> 
    <v1:author> 
     <v1:role>author</v1:role> 
     <v1:person> 
      <v1:firstName>Jane</v1:firstName> 
      <v1:lastName>Smith</v1:lastName> 
     </v1:person> 
     <v1:person> 
      <v1:firstName>John</v1:firstName> 
      <v1:lastName>Doe</v1:lastName> 
     </v1:person> 
    </v1:author> 
    </v1:persons> 

Шаблон сопоставления v1:person копируют все v1:person узлов, которые являются потомками книги с тем же id.
Сохранено Demo с дополнительной второй книгой с другим id.

+0

Спасибо, что почти сделали это. Я изменил в xsl: template v1: person to v1: author, и он дал мне именно то, что мне было нужно. –

Смежные вопросы