简体   繁体   English

在 xslt 中合并 xml 文件时添加一次顶级标签

[英]add top level tag once while merging xml files in xslt

I'm trying to merge multiple xml files in specific folder using xslt and saxon-HE 9.9.1 .NET.我正在尝试使用 xslt 和 saxon-HE 9.9.1 .NET 合并特定文件夹中的多个 xml 文件。 I need to create a generic merger so that I will not add a static tag inside the template to use it with different nodes' names, I tried to make a loop to add the root or the top level tag once in the beginning but it also close the tag before the xml end but there is an issue with the top level tag Example: XML File1:我需要创建一个通用合并,这样我就不会在模板中添加静态标签以将其与不同节点的名称一起使用,我尝试在开始时创建一个循环以添加根或顶级标签,但它也在 xml 结束之前关闭标记,但顶级标记存在问题 示例:XML File1:

<Arr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <Src>
    <name>C</name>
    <pr>pr</pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh1</name>
        <type>xx1</typ>
      </Q>
    </par>
    <st />
 </Src>
 <Src>
    <name>C</name>
    <pr></pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh2</name>
        <type>xx2</typ>
      </Q>
    </par>
    <st>
      <Src>
        <name>st1</name>
        <pr>prst1</pr>
        <par>
          <Q>
            <isC>false</isC>
            <name>q1</name>
            <type>t1</type>
          </Q>
          <Q>
            <isC>false</isC>
            <name>q2</name>
            <type>t2</type>
          </Q>
        </par>
        <st />
      </Src>
    </st>
  </Src>
 </Arr>

XML File2: XML文件2:

<Arr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <Src>
    <name>CFile2</name>
    <pr>C2</pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh1</name>
        <type>xx1</typ>
      </Q>
    </par>
    <st />
 </Src>
 </Arr>

expected output:预期输出:

<Arr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <Src>
    <name>C</name>
    <pr>pr</pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh1</name>
        <type>xx1</typ>
      </Q>
    </par>
    <st />
 </Src>
 <Src>
    <name>C</name>
    <pr></pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh2</name>
        <type>xx2</typ>
      </Q>
    </par>
    <st>
      <Src>
        <name>st1</name>
        <pr>prst1</pr>
        <par>
          <Q>
            <isC>false</isC>
            <name>q1</name>
            <type>t1</type>
          </Q>
          <Q>
            <isC>false</isC>
            <name>q2</name>
            <type>t2</type>
          </Q>
        </par>
        <st />
      </Src>
    </st>
  </Src>
  <Src>
    <name>CFile2</name>
    <pr>C2</pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh1</name>
        <type>xx1</typ>
      </Q>
    </par>
    <st />
  </Src>
 </Arr>

my current template which is produces wrong output because of the top level tag closure由于顶级标签关闭,我当前的模板会产生错误的输出

<?xml version="1.0" encoding="windows-1256"?>   
<xsl:stylesheet version="3.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:user="http://tempuri.org/msxsl" >     
 <xsl:output method="xml" indent="yes" encoding="windows-1256" />

<xsl:template name="main">
 
 <xsl:for-each select="collection('.?select=*.xml')/*">
  <xsl:choose>
        <xsl:when test="position() = 1">
          <xsl:copy>
        <xsl:copy-of select="/*/node()"/> 
        </xsl:copy>
   
        </xsl:when>
        <xsl:otherwise>
         <xsl:copy-of select="/*/node()"/> 
        </xsl:otherwise>
      </xsl:choose>
      
</xsl:for-each> 

</xsl:template>

</xsl:stylesheet>

I run from the cmd with the following command:我使用以下命令从 cmd 运行:

transform -it:main -xsl:merge_xml.xslt -o:output.xml

my current output which is wrong我当前的输出是错误的

<Arr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <Src>
    <name>C</name>
    <pr>pr</pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh1</name>
        <type>xx1</typ>
      </Q>
    </par>
    <st />
 </Src>
 <Src>
    <name>C</name>
    <pr></pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh2</name>
        <type>xx2</typ>
      </Q>
    </par>
    <st>
      <Src>
        <name>st1</name>
        <pr>prst1</pr>
        <par>
          <Q>
            <isC>false</isC>
            <name>q1</name>
            <type>t1</type>
          </Q>
          <Q>
            <isC>false</isC>
            <name>q2</name>
            <type>t2</type>
          </Q>
        </par>
        <st />
      </Src>
    </st>
  </Src>
</Arr>
  <Src>
    <name>CFile2</name>
    <pr>C2</pr>
    <par>
      <Q>
        <isC>false</isC>
        <name>hrh1</name>
        <type>xx1</typ>
      </Q>
    </par>
    <st />
  </Src>

I would simply use我会简单地使用

 <xsl:param name="uris" select="uri-collection('.?select=*.xml')"/>

 <xsl:template name="xsl:initial-template">
    <xsl:copy select="$uris => head() => doc()/*">
      <xsl:copy-of select="($uris ! doc(.))/*/node()"/>
    </xsl:copy>
  </xsl:template>

To be able to switch to streaming if Saxon EE is an option one could try如果 Saxon EE 是一个可以尝试的选项,则能够切换到流媒体

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all" expand-text="yes">

    <xsl:function name="mf:merge" as="document-node()">
        <xsl:param name="uris"/>
        <xsl:source-document href="{head($uris)}" streamable="yes">
            <xsl:document>
                <xsl:copy select="*">
                    <xsl:copy-of select="node()"/>
                    <xsl:iterate select="tail($uris)">
                        <xsl:source-document href="{.}" streamable="yes">
                            <xsl:copy-of select="*/node()"/>
                        </xsl:source-document>
                    </xsl:iterate>
                </xsl:copy>
            </xsl:document>
        </xsl:source-document>
    </xsl:function>

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

    <xsl:template name="xsl:initial-template">
        <xsl:sequence select="mf:merge(uri-collection('?select=*.xml'))"/>
    </xsl:template>

</xsl:stylesheet>

Martin's solution will work, but I would do:马丁的解决方案会奏效,但我会这样做:

  <xsl:template name="xsl:initial-template">
    <xsl:variable name="coll" select="collection('.?select=*.xml')"/>
    <xsl:copy select="$coll[1]/*">
      <xsl:copy-of select="$coll/*/*"/>
    </xsl:copy>
  </xsl:template>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM