【问题标题】:add top level tag once while merging xml files in xslt在 xslt 中合并 xml 文件时添加一次顶级标记
【发布时间】:2020-08-31 14:31:21
【问题描述】:

我正在尝试使用 xslt 和 saxon-HE 9.9.1 .NET 合并特定文件夹中的多个 xml 文件。我需要创建一个通用合并,这样我就不会在模板中添加一个静态标签来将它与不同节点的名称一起使用,我试图在开始时创建一个循环来添加根标签或顶级标签,但它也在 xml 结束之前关闭标签,但顶级标签存在问题 例子: XML 文件 1:

<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 文件 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>

预期输出:

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

我当前的模板由于顶级标签关闭而产生错误的输出

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

我使用以下命令从 cmd 运行:

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

我当前的输出是错误的

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

【问题讨论】:

    标签: xml xslt tags saxon merge-file


    【解决方案1】:

    Martin 的解决方案会奏效,但我会这样做:

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

    【讨论】:

      【解决方案2】:

      我会简单地使用

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

      如果 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>
      

      【讨论】:

      • 感谢您的回答,我正在与 Saxon HE 合作,第一个解决方案可能有效,但它在 fn:doc() 的第一个参数不允许包含多个项目的序列 我还有一个问题 head() 函数给了我文档的顶部,对吗?您是如何获得这些信息的,我只是要求进行知识交流
      • @Yara,查看编辑,我使用了错误的运算符。至于函数的定义,我建议你从w3.org/TR/xpath-functions/开始
      • maxtoroq.github.io/xpath-ref 可能也有帮助,它是根据规范编译的,但可能更易于浏览。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      • 1970-01-01
      • 2013-10-02
      • 2021-11-24
      • 1970-01-01
      相关资源
      最近更新 更多