转换包含子节点列表的xml以分隔xml

时间:2018-08-31 08:41:15

标签: xml xslt

我有一个xml输入,其中包含xml子节点列表。我想基于xml子节点分隔此xml。但是在分离时,父节点需要保留。我尝试使用for-each,但是输出不符合预期。

输入

Car

预期产量

<node1>
   <id>1</id>
   <code>abcd</code>
   <version>v1</version>
   <node2>
      <market>india</market>
      <active>true</active>
   </node2>
   <node2>
      <market>US</market>
      <active>true</active>
   </node2>
   <mixins>
      <node3>
         <ref>MZ-SR-P004</ref>
         <type>Commercial</type>
      </node3>
   </mixins>
</node1>

是否可以使用xslt做到这一点。我尝试了下面的XSLT转换

XSLT

<node1>
   <id>1</id>
   <code>abcd</code>
   <version>v1</version>
   <node2>
      <market>india</market>
      <active>true</active>
   </node2>
   <mixins>
      <node3>
         <ref>MZ-SR-P004</ref>
         <type>Commercial</type>
      </node3>
   </mixins>
</node1>
<node1>
   <id>1</id>
   <code>abcd</code>
   <version>v1</version>
   <node2>
      <market>US</market>
      <active>true</active>
   </node2>
   <mixins>
      <node3>
         <ref>MZ-SR-P004</ref>
         <type>Commercial</type>
      </node3>
   </mixins>
</node1>

我当前的输出如下所示

当前xml输出

<?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:template match="@*|node()">
         <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
         <xsl:apply-templates />
    </xsl:template>
    <xsl:template match="node2">
         <xsl:for-each select="node2">
            <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
         </xsl:for-each>    
    </xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

在模板匹配node2中,然后执行xsl:for-each以选择node2,但这将在您正在匹配的当前node2的子元素中查找,所以什么也没有将被选中。

您的模板可能应该选择node1。然后,在xsl:for-each内,您需要创建node1并复制作为当前node2或其他命名节点的所有子节点

尝试使用此XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="node1">
        <xsl:for-each select="node2">
            <node1>
                <xsl:apply-templates select="../*[generate-id() = generate-id(current()) or not(self::node2)]" />
            </node1>
        </xsl:for-each>    
    </xsl:template>
</xsl:stylesheet>

请注意,我还从身份模板中删除了<xsl:apply-templates />

答案 1 :(得分:1)

更通用的XSLT 2或3方法将是选择节点(例如node1/node2),然后通过执行带有存储当前{{1}的隧道参数的身份复制的模式来推送整个树}以确保该模式在node2上匹配时,仅输出此特定的node2并忽略所有其他模式:

node2

https://xsltfiddle.liberty-development.net/gWmuiJF