Xml XSLT将子节点拆分为新节点

Xml XSLT将子节点拆分为新节点,xml,xslt,Xml,Xslt,我需要转换XML文件的结构,并认为XSLT可能是最好的解决方案(这就是它的目的吗?),我有一些XSLT的经验,但它有点有限,所以我需要一些指导 情况如下:;我有一个包含一个或多个记录的XML。每个记录有一组字段,每个字段有一组子字段。子字段的顺序很重要。需要做的是,需要转换输入结构,以便子字段代码A和K的每次出现都应在输出中产生一个新字段(新代码和子字段K重命名为A),子字段位于子字段A或K之后,如下例所示。子字段K的数量是任意的,不同的记录可能会有所不同,xslt需要稍微通用一些 以下是我的输

我需要转换XML文件的结构,并认为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>

Abc
扩散系数
Fgh
IJ
吉隆坡
操作
... 更多数据字段。。。
所需的输出如下:

    <?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>

Abc
扩散系数
Fgh
IJ
吉隆坡
操作
... 更多数据字段。。。
如果有人能为我提供一些xslt示例,至少能为我指明正确的方向,我将不胜感激

编辑:只是澄清一下。A和K子字段之间可以有任意数量的子字段。


<?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>

假设您可以使用诸如Saxon 9、Altova或XmlPrime之类的XSLT 2.0处理器

<?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>

Abc
扩散系数
Fgh
IJ
吉隆坡
操作
... 更多数据字段。。。
进入


Abc
扩散系数
Fgh
IJ
吉隆坡
操作
如果您需要XSLT1.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>

A.

应该可以。

输入有
字段代码=“123”
,为什么输出有
字段代码=“124”
?您可以使用XSLT2.0吗?使用
看起来是个不错的选择。是每个奇数子字段都需要与下面的偶数子字段配对,还是每个a或K子字段都需要配对?或者是同一件事?@MartinHonnen field code=“124”在输出中是正确的。可以说,这是一种格式翻译。我在VisualStudio2012中写这篇文章,不确定XSLT2.0支持。将需要检查。@michael.hor257k每一个A或K应产生一个代码为124的新字段。输入只能出现一个子字段A,但子字段K可以出现多次。@EmilTinebo,在.NET版本中有第三方XSLT 2.0处理器,如Saxon 9,XmlPrime或AltovaXML,但Microsoft的XslCompiledTransform或MSXML仅支持XSLT 1.0。根据您的最新解释,在
template match=“field”
的情况下,您可能需要
template match=“field[@code=23]”
,如果您只想转换这些字段元素,那么改变它应该不会太困难。这几乎奏效了。我新的124个字段中的子字段代码显示为K,而不是A。。。不知道为什么。。。有什么线索吗?请更详细地解释一下您现在尝试了什么,XSLT 1.0样式表,XSLT 2.0样式表,如图所示的输入或其他什么?由于我的示例正在执行
A
,我不明白为什么您会得到
K
,而不是
A
。哦,对不起!我尝试了XSLT1.0版本。从visual studio运行XSLT模板
中的断点永远不会被击中…我有另一个似乎正在运行的模板,而不是您提供的模板<代码>
<?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>