使用这些元素之一将具有X元素的一个节点拆分为X节点

时间:2013-03-10 13:25:42

标签: xml xslt

是否有可能实现这样的转变:

源XML:

<Item>
  <stockcode>XXX1</stockcode>
  <vehicle>Bentley</vehicle>
  <model>Continental GT (2006-)</model>
  <model>Continental Flying Spur (2006-)</model>
  <width>9</width>
  <wheel_size>20</wheel_size>  
  <offset>40</offset>
  <bolt_pattermn>5x112</bolt_pattermn>
  <brand>AEZ</brand>
  <Velg_ID>AEZ Myta</Velg_ID>
  <kit1>DK-ZJAE x1</kit1>
</Item>

目标XML:

<Item>
  <stockcode>XXX1</stockcode>
  <vehicle>Bentley</vehicle>
  <model>Continental GT (2006-)</model>
  <width>9</width>
  <wheel_size>20</wheel_size>    
  <offset>40</offset>
  <bolt_pattermn>5x112</bolt_pattermn>
  <brand>AEZ</brand>
  <Velg_ID>AEZ Myta</Velg_ID>
  <kit1>DK-ZJAE x1</kit1>
  <qty_available>8.00000000</qty_available>
  <price>174.00</price>
  <picture>41010</picture>
  <pkpcena>195.4999</pkpcena>
</Item>
<Item>
  <stockcode>XXX1</stockcode>
  <vehicle>Bentley</vehicle>
  <model>Continental Flying Spur (2006-)</model>
</Item>

在源XML中,1个节点有X个元素,X节点必须分成1个元素。目标XML可以包含源代码中的所有元素,也可以只包含元素<vehicle><model>

如果是 - 可以有人提示吗? ; - )

谢谢!

2 个答案:

答案 0 :(得分:1)

这样就可以了:

<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="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="//model" mode="split" />
    </root>
  </xsl:template>

  <xsl:template match="model" mode="split">
    <xsl:apply-templates select="..">
      <xsl:with-param name="currentModel" select="." />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Item">
    <xsl:param name="currentModel" />

    <xsl:copy>
      <xsl:apply-templates
         select="@* | node()[not(self::model)] | $currentModel" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

当应用于您的样本输入时,会产生:

<root>
  <Item>
    <stockcode>XXX1</stockcode>
    <vehicle>Bentley</vehicle>
    <model>Continental GT (2006-)</model>
    <width>9</width>
    <wheel_size>20</wheel_size>
    <offset>40</offset>
    <bolt_pattermn>5x112</bolt_pattermn>
    <brand>AEZ</brand>
    <Velg_ID>AEZ Myta</Velg_ID>
    <kit1>DK-ZJAE x1</kit1>
  </Item>
  <Item>
    <stockcode>XXX1</stockcode>
    <vehicle>Bentley</vehicle>
    <model>Continental Flying Spur (2006-)</model>
    <width>9</width>
    <wheel_size>20</wheel_size>
    <offset>40</offset>
    <bolt_pattermn>5x112</bolt_pattermn>
    <brand>AEZ</brand>
    <Velg_ID>AEZ Myta</Velg_ID>
    <kit1>DK-ZJAE x1</kit1>
  </Item>
</root>

这是一个实现,我已经缩短了我的上述方法,并提出了Dimitre技术的一些指示:

<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="model">
    <xsl:apply-templates select=".." mode="gen">
      <xsl:with-param name="currentModel" select="." />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="@* | node()" mode="gen">
    <xsl:param name="currentModel" select="/.." />

    <xsl:copy>
      <xsl:apply-templates
         select="@* | node()[not(self::model)] | $currentModel" 
         mode="gen" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="text()" />
</xsl:stylesheet>

答案 1 :(得分:0)

<强>予。这种转变:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="text()"/>

 <xsl:template match="model">
  <xsl:apply-templates select=".." mode="gen">
   <xsl:with-param name="pInclude" select="."/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="node()|@*" mode="gen">
  <xsl:param name="pInclude" select="/.."/>
      <xsl:copy>
       <xsl:apply-templates mode="gen" select=
        "node()[not(name()=name($pInclude)) or count(.|$pInclude)=1]|@*" >
        <xsl:with-param name="pInclude" select="$pInclude"/>
       </xsl:apply-templates>
      </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

应用于此XML文档(提供的文档添加了第三个model和多个Item元素):

<t>
    <Item>
        <stockcode>XXX1</stockcode>
        <vehicle>Bentley</vehicle>
        <model>Continental GT (2006-)</model>
        <model>Continental Flying Spur (2006-)</model>
        <model>Galactic Flying Spur (2006-)</model>
        <width>9</width>
        <wheel_size>20</wheel_size>
        <offset>40</offset>
        <bolt_pattermn>5x112</bolt_pattermn>
        <brand>AEZ</brand>
        <Velg_ID>AEZ Myta</Velg_ID>
        <kit1>DK-ZJAE x1</kit1>
    </Item>
    <Item>
        <stockcode>XXX1</stockcode>
        <vehicle>Bentley</vehicle>
        <model>XXX Continental GT (2006-)</model>
        <model>YYY Continental Flying Spur (2006-)</model>
        <model>ZZZ Galactic Flying Spur (2006-)</model>
        <width>9</width>
        <wheel_size>20</wheel_size>
        <offset>40</offset>
        <bolt_pattermn>5x112</bolt_pattermn>
        <brand>AEZ</brand>
        <Velg_ID>AEZ Myta</Velg_ID>
        <kit1>DK-ZJAE x1</kit1>
    </Item>
</t>

会产生想要的正确结果:

<Item>
   <stockcode>XXX1</stockcode>
   <vehicle>Bentley</vehicle>
   <model>Continental GT (2006-)</model>
   <width>9</width>
   <wheel_size>20</wheel_size>
   <offset>40</offset>
   <bolt_pattermn>5x112</bolt_pattermn>
   <brand>AEZ</brand>
   <Velg_ID>AEZ Myta</Velg_ID>
   <kit1>DK-ZJAE x1</kit1>
</Item>
<Item>
   <stockcode>XXX1</stockcode>
   <vehicle>Bentley</vehicle>
   <model>Continental Flying Spur (2006-)</model>
   <width>9</width>
   <wheel_size>20</wheel_size>
   <offset>40</offset>
   <bolt_pattermn>5x112</bolt_pattermn>
   <brand>AEZ</brand>
   <Velg_ID>AEZ Myta</Velg_ID>
   <kit1>DK-ZJAE x1</kit1>
</Item>
<Item>
   <stockcode>XXX1</stockcode>
   <vehicle>Bentley</vehicle>
   <model>Galactic Flying Spur (2006-)</model>
   <width>9</width>
   <wheel_size>20</wheel_size>
   <offset>40</offset>
   <bolt_pattermn>5x112</bolt_pattermn>
   <brand>AEZ</brand>
   <Velg_ID>AEZ Myta</Velg_ID>
   <kit1>DK-ZJAE x1</kit1>
</Item>
<Item>
   <stockcode>XXX1</stockcode>
   <vehicle>Bentley</vehicle>
   <model>XXX Continental GT (2006-)</model>
   <width>9</width>
   <wheel_size>20</wheel_size>
   <offset>40</offset>
   <bolt_pattermn>5x112</bolt_pattermn>
   <brand>AEZ</brand>
   <Velg_ID>AEZ Myta</Velg_ID>
   <kit1>DK-ZJAE x1</kit1>
</Item>
<Item>
   <stockcode>XXX1</stockcode>
   <vehicle>Bentley</vehicle>
   <model>YYY Continental Flying Spur (2006-)</model>
   <width>9</width>
   <wheel_size>20</wheel_size>
   <offset>40</offset>
   <bolt_pattermn>5x112</bolt_pattermn>
   <brand>AEZ</brand>
   <Velg_ID>AEZ Myta</Velg_ID>
   <kit1>DK-ZJAE x1</kit1>
</Item>
<Item>
   <stockcode>XXX1</stockcode>
   <vehicle>Bentley</vehicle>
   <model>ZZZ Galactic Flying Spur (2006-)</model>
   <width>9</width>
   <wheel_size>20</wheel_size>
   <offset>40</offset>
   <bolt_pattermn>5x112</bolt_pattermn>
   <brand>AEZ</brand>
   <Velg_ID>AEZ Myta</Velg_ID>
   <kit1>DK-ZJAE x1</kit1>
</Item>

<强> II。一种更通用且仍然很短的转换,其中要拆分的元素名称作为(外部)参数传递:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:param name="pName" select="'model'"/>

 <xsl:template match="*">
  <xsl:apply-templates select="parent::*[$pName = name(current())]" mode="gen">
   <xsl:with-param name="pInclude" select="."/>
  </xsl:apply-templates>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="node()|@*" mode="gen">
  <xsl:param name="pInclude" select="/.."/>

      <xsl:copy>
       <xsl:apply-templates mode="gen" select=
       "node()[not(name()=name($pInclude)) or count(.|$pInclude)=1]|@*" >
        <xsl:with-param name="pInclude" select="$pInclude"/>
       </xsl:apply-templates>
      </xsl:copy>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

<强> III。这种通用问题的最通用解决方案:

请参阅此答案:https://stackoverflow.com/a/8597577/36305