[英]add top level tag once while merging xml files in xslt
我正在尝试使用 xslt 和 saxon-HE 9.9.1 .NET 合并特定文件夹中的多个 xml 文件。 我需要创建一个通用合并,这样我就不会在模板中添加静态标签以将其与不同节点的名称一起使用,我尝试在开始时创建一个循环以添加根或顶级标签,但它也在 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文件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>
我会简单地使用
<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>
马丁的解决方案会奏效,但我会这样做:
<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.