2014-01-16 5 views
0

Мне нужно преобразовать структуру XML-файла, а фигурируемый XSLT может быть лучшим решением (это то, для чего это правильно?) У меня есть некоторый опыт работы с XSLT, но он немного ограничен, поэтому мне нужно немного руководство.XSLT Разделить дочерние элементы на новые узлы

Сценарий выглядит следующим образом; У меня есть XML, содержащий одну или несколько записей. Каждая запись имеет набор полей, и каждое поле имеет набор подполей. Порядок вспомогательных полей значителен. Что нужно сделать, так это то, что входная структура должна быть преобразована так, чтобы каждое возникновение кодов подполя A и K приводило к появлению нового поля (с новым кодом и подполем K, переименованным в A) на выходе с подпунктом поля, которые следует за подполем A или K, как показано в примере ниже. Количество подполей K произвольно и может отличаться от записи, чтобы записать xslt, чтобы быть немного общим.

Вот мой вход XML:

<?xml version="1.0" encoding="UTF-8" ?> 
    <record> 
     <field code="123"> 
     <subfield code="A">Abc</subfield> 
     <subfield code="B">De</subfield> 
     <subfield code="K">Fgh</subfield> 
     <subfield code="C">IJ</subfield> 
     <subfield code="K">Klmn</subfield> 
     <subfield code="D">OP</subfield> 
    </field> 
    <field>... more datafields... </field> 
    </record> 

Нужный выход следующим образом:

<?xml version="1.0" encoding="UTF-8" ?> 
    <record> 
     <field code="124"> 
     <subfield code="A">Abc</subfield> 
     <subfield code="B">De</subfield> 
    </field> 
    <field code="124"> 
     <subfield code="A">Fgh</subfield> 
     <subfield code="C">IJ</subfield> 
    </field> 
    <field code="124"> 
     <subfield code="A">Klmn</subfield> 
     <subfield code="D">OP</subfield> 
    </field> 
    <field>... more datafields... </field> 
    </record> 

Если кто-нибудь может дать мне какой-то образец XSLT, что по крайней мере указывает меня в правильном направлении, я я был бы очень обязан.

EDIT: Просто уточнить. Между подполями A и K может быть любое количество подполей.

+0

Вход имеет код поля = 123 "', почему на выходе есть поле code = "124" '? И можете ли вы использовать XSLT 2.0? Похоже, хорошая работа для использования ' ...'. –

+0

Это * каждое нечетное подполе *, которое должно быть сопряжено со следующим даже одним, или * каждым подполем A или K *? Или это то же самое? –

+0

Код поля @MartinHonnen = "124" правильный на выходе. Это, так сказать, формат перевода. Я пишу это в Visual Studio 2012, не уверен в поддержке XSLT 2.0. Вам нужно будет изучить это. –

ответ

1

Предполагая, что процессор XSLT 2.0, как Saxon 9 или Altova или XmlPrime вы можете использовать

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

<xsl:strip-space elements="*"/> 

<xsl:output indent="yes"/> 

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

<xsl:template match="field"> 
    <xsl:for-each-group select="subfield" group-starting-with="subfield[@code = ('A', 'K')]"> 
    <field code="124"> 
     <xsl:apply-templates select="current-group()"/> 
    </field> 
    </xsl:for-each-group> 
</xsl:template> 

<xsl:template match="subfield/@code[. = 'K']"> 
    <xsl:attribute name="{name()}" select="'A'"/> 
</xsl:template> 

</xsl:stylesheet> 

, который превращает

<?xml version="1.0" encoding="UTF-8" ?> 
    <record> 
     <field code="123"> 
     <subfield code="A">Abc</subfield> 
     <subfield code="B">De</subfield> 
     <subfield code="K">Fgh</subfield> 
     <subfield code="C">IJ</subfield> 
     <subfield code="K">Klmn</subfield> 
     <subfield code="D">OP</subfield> 
    </field> 
    <field>... more datafields... </field> 
    </record> 

в

<record> 
    <field code="124"> 
     <subfield code="A">Abc</subfield> 
     <subfield code="B">De</subfield> 
    </field> 
    <field code="124"> 
     <subfield code="A">Fgh</subfield> 
     <subfield code="C">IJ</subfield> 
    </field> 
    <field code="124"> 
     <subfield code="A">Klmn</subfield> 
     <subfield code="D">OP</subfield> 
    </field> 
</record> 

Если вам нужен Решение XSLT 1.0 затем

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

<xsl:strip-space elements="*"/> 

<xsl:output indent="yes"/> 

<xsl:key name="sub" match="subfield[not(@code = 'A' or @code = 'K')]" 
    use="generate-id(preceding-sibling::subfield[@code = 'A' or @code = 'K'][1])"/> 

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

<xsl:template match="field"> 
    <xsl:apply-templates select="subfield[@code = 'A' or @code = 'K']" mode="group"/> 
</xsl:template> 

<xsl:template match="subfield[@code = 'A' or @code = 'K']" mode="group"> 
    <field code="124"> 
    <xsl:apply-templates select=". | key('sub', generate-id())"/> 
    </field> 
</xsl:template> 

<xsl:template match="subfield/@code[. = 'K']"> 
    <xsl:attribute name="{name()}">A</xsl:attribute> 
</xsl:template> 

</xsl:stylesheet> 

следует делать.

+0

Это может сработать! Я попробую это через мгновение! –

+0

Исходя из вашего последнего объяснения, возможно, что в поле 'template match =" вам понадобится поле 'template match =" [@code = 23] "', это не должно быть слишком сложно изменить, если вы просто хотите преобразовать эти элементы поля. –

+0

Это почти сработало. Коды подполя в моих новых 124 областях появились как K, а не A ... не уверены, почему ... какие-то подсказки? –

0
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

<xsl:template match="subfield"> 
    <field code="{../@code}"> 
     <xsl:copy-of select="." /> 
     <xsl:copy-of select="following-sibling::subfield[1]" /> 
    </field> 
</xsl:template> 

<xsl:template match="record"> 
    <xsl:apply-templates select="//subfield[position() mod 2 = 1]" /> 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:apply-templates select="record" /> 
</xsl:template> 

</xsl:stylesheet> 
Смежные вопросы