Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将包含子节点列表的xml转换为单独的xml_Xml_Xslt - Fatal编程技术网

将包含子节点列表的xml转换为单独的xml

将包含子节点列表的xml转换为单独的xml,xml,xslt,Xml,Xslt,我有一个包含xml子节点列表的xml输入。我想根据xml子节点分离此xml。但在分离时,需要保留父节点。我试着使用for-each,但输出并不像预期的那样 输入 预期产量 <node1> <id>1</id> <code>abcd</code> <version>v1</version> <node2> <market>india</market&

我有一个包含xml子节点列表的xml输入。我想根据xml子节点分离此xml。但在分离时,需要保留父节点。我试着使用for-each,但输出并不像预期的那样

输入

预期产量

<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>
是否可以使用xslt实现这一点。我尝试了下面的XSLT转换

XSLT


在模板匹配
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>


注意,我还从标识模板中删除了

在模板匹配
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>


注:我还从标识模板中删除了

更通用的XSLT 2或3方法是选择节点(例如
node1/node2
)然后通过一个模式推送完整的树,使用存储当前
node2
的隧道参数进行身份复制,以确保当该模式在
node2
上匹配时,它只输出该特定的
node2
,而忽略所有其他模式:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:mode name="reconstruct" on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:for-each select="node1/node2">
        <xsl:apply-templates select="/" mode="reconstruct">
            <xsl:with-param name="copy" tunnel="yes" select="current()"/>
        </xsl:apply-templates>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="node2" mode="reconstruct">
      <xsl:param name="copy" tunnel="yes"/>
      <xsl:sequence select=".[. is $copy]"/>
  </xsl:template>

</xsl:stylesheet>


更通用的XSLT2或3方法是选择节点(例如,
node1/node2
)然后通过一个模式推送完整的树,使用存储当前
node2
的隧道参数进行身份复制,以确保当该模式在
node2
上匹配时,它只输出该特定的
node2
,而忽略所有其他模式:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:mode name="reconstruct" on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:for-each select="node1/node2">
        <xsl:apply-templates select="/" mode="reconstruct">
            <xsl:with-param name="copy" tunnel="yes" select="current()"/>
        </xsl:apply-templates>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="node2" mode="reconstruct">
      <xsl:param name="copy" tunnel="yes"/>
      <xsl:sequence select=".[. is $copy]"/>
  </xsl:template>

</xsl:stylesheet>


您能否向我们展示您现在的输出,以及您想要的输出?您能否向我们展示您当前使用
xsl:for each
的尝试。它可能不起作用,但实际上你可能并不遥远。谢谢,这是我试过的。请编辑问题,而不是在注释中添加代码。使用更多信息编辑问题。您能否向我们展示您现在的输出,以及您想要的输出?您能否向我们展示您当前使用
xsl:for each
的尝试。它可能不起作用,但实际上你可能并不遥远。谢谢,这是我试过的。请编辑问题,而不是在注释中添加代码。请使用详细信息编辑问题
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:mode name="reconstruct" on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:for-each select="node1/node2">
        <xsl:apply-templates select="/" mode="reconstruct">
            <xsl:with-param name="copy" tunnel="yes" select="current()"/>
        </xsl:apply-templates>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="node2" mode="reconstruct">
      <xsl:param name="copy" tunnel="yes"/>
      <xsl:sequence select=".[. is $copy]"/>
  </xsl:template>

</xsl:stylesheet>