我有几个XML文件,如下所示:
档案: 1.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config>
<info>
<info1>val1</info1>
<info2>val2</info2>
</info>
<info>
<info1>val3</info1>
<info2>val4</info2>
</info>
</config>
档案: 2.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config>
<info>
<info1>val5</info1>
<info2>val6</info2>
</info>
<info>
<info1>val7</info1>
<info2>val8</info2>
</info>
</config>
档案: 3.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config>
<info>
<info1>val9</info1>
<info2>val10</info2>
</info>
<info>
<info1>val11</info1>
<info2>val12</info2>
</info>
</config>
使用XSLT2.0(saxon),我想合并它们并添加到每个节点:
<info3>XXX</info3>
以及
<file>filename.xml</file>
filename.xml是从中复制信息的文件。
输出应如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config>
<info>
<info1>val1</info1>
<info2>val2</info2>
<info3>XXX</info3>
<file>1.xml</file>
</info>
<info>
<info1>val3</info1>
<info2>val4</info2>
<info3>XXX</info3>
<file>1.xml</file>
</info>
<info>
<info1>val5</info1>
<info2>val6</info2>
<info3>XXX</info3>
<file>2.xml</file>
</info>
<info>
<info1>val7</info1>
<info2>val8</info2>
<info3>XXX</info3>
<file>2.xml</file>
</info>
<info>
<info1>val9</info1>
<info2>val10</info2>
<info3>XXX</info3>
<file>3.xml</file>
</info>
<info>
<info1>val11</info1>
<info2>val12</info2>
<info3>XXX</info3>
<file>3.xml</file>
</info>
</config>
到目前为止,我已经能够通过创建一个XML文件来合并文件,该文件列出了我要合并的文件(merge.xml):
<mergeData newRoot="config">
<filelist>
<fileItem>1.xml</fileItem>
<fileItem>2.xml</fileItem>
<fileItem>3.xml</fileItem>
</filelist>
</mergeData>
使用以下XSL(merge.xsl):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="#all">
<xsl:param name="new">
<info>XXX</info>
</xsl:param>
<xsl:template match="/">
<xsl:element name="{mergeData/@newRoot}">
<xsl:apply-templates select="mergeData/fileList/fileItem"/>
</xsl:element>
</xsl:template>
<xsl:template match="fileItem">
<xsl:apply-templates select="document(translate(., '\', '/'))/config/*"/>
</xsl:template>
<xsl:template match="config/*">
<xsl:copy>
<xsl:copy-of select="node()"/>
<xsl:copy-of select="$new"/>
</xsl:copy>
<file><xsl:value-of select="tokenize(document-uri(.), '/')[last()]"/></file>
</xsl:template>
我应该如何修改XSL以同时获取每个信息的文件名。
答案 0 :(得分:0)
以下XSLT产生了您所需的结果:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:param name="new">
<info>XXX</info>
</xsl:param>
<xsl:template match="/mergeData">
<config>
<xsl:for-each select="filelist/fileItem">
<xsl:variable name="filename" select="text()"/>
<xsl:for-each select="document($filename)/config/info">
<info>
<xsl:copy-of select="./*"/>
<xsl:element name="info{count(*)+1}">
<xsl:value-of select="$new"/>
</xsl:element>
<file><xsl:value-of select="$filename"/></file>
</info>
</xsl:for-each>
</xsl:for-each>
</config>
</xsl:template>
</xsl:stylesheet>
注意:
newRoot
。tokenize
会将其推回到XSLT 2.0或扩展函数。答案 1 :(得分:0)
您唯一应该做的就是在file
内移动xsl:copy
。
示例(带有其他一些小mod):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="#all">
<xsl:output indent="yes"/>
<xsl:param name="new">
<info3>XXX</info3>
</xsl:param>
<xsl:template match="/">
<xsl:element name="{mergeData/@newRoot}">
<xsl:apply-templates select="mergeData/filelist/fileItem"/>
</xsl:element>
</xsl:template>
<xsl:template match="fileItem">
<xsl:apply-templates select="document(translate(., '\', '/'))/config/*"/>
</xsl:template>
<xsl:template match="config/*">
<xsl:copy>
<xsl:copy-of select="node(),$new"/>
<file><xsl:value-of select="tokenize(document-uri(/), '/')[last()]"/></file>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
您也可以使用collection()
执行此操作,而不是创建单独的mergeData.xml
文件:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="newRoot" select="'config'"/>
<xsl:param name="new">
<info3>XXX</info3>
</xsl:param>
<xsl:template match="/">
<xsl:element name="{$newRoot}">
<xsl:apply-templates select="collection('file:///C:/some/path?select=[0-9]*.xml')/*/info"/>
</xsl:element>
</xsl:template>
<xsl:template match="info">
<xsl:copy>
<xsl:copy-of select="@*|node(),$new"/>
<file><xsl:value-of select="tokenize(document-uri(/),'/')[last()]"/></file>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
由于您使用的是Saxon,因此另外一种方法是使用saxon:discard-document()
和mergeData.xml
输入。如果mergeData.xml
中列出了大量文件,则可以帮助消耗内存。 (它确实需要Saxon PE或EE或允许扩展功能的旧版Saxon。)
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="new">
<info3>XXX</info3>
</xsl:param>
<xsl:template match="/mergeData">
<xsl:element name="{@newRoot}">
<xsl:apply-templates select="filelist/fileItem"/>
</xsl:element>
</xsl:template>
<xsl:template match="fileItem">
<xsl:apply-templates select="document(.)/saxon:discard-document(.)/*/*" xmlns:saxon="http://saxon.sf.net/"/>
</xsl:template>
<xsl:template match="info">
<xsl:copy>
<xsl:copy-of select="@*|node(),$new"/>
<file><xsl:value-of select="tokenize(document-uri(/),'/')[last()]"/></file>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>