使用 Java 使用 XSLT 将 xml 拆分为多个文件
Split xml using XSLT to multiple files using Java
我有一个 XML 文件,需要根据 Xpath 变量上的匹配项(包含)进行拆分。
`<Apps>
<App>
<AppID>49O</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>715</AppID>
<Type>DP Pay</Type>
</App>
<App>
<AppID>716</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>725</AppID>
<Type>CP Pay</Type>
</App>
<App>
<AppID>728</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>728</AppID>
<Type>CP Pay</Type>
</App>
</Apps>`
所以拆分 xml 的条件是
1. Apps/App/Type/text()->包含'MP'
2. Apps/App/Type/text()->包含'DP'
以下是预期输出:
所有包含 Type 为 'MP' 的 App 节点都应该在一个文件中 -> MP.xml.
<Apps>
<App>
<AppID>49O</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>716</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>728</AppID>
<Type>MP Pay</Type>
</App>
</Apps>
所有包含 Type 为 'DP' 的 App 节点都应该在一个文件中 -> DP.xml.
<Apps>
<App>
<AppID>715</AppID>
<Type>DP Pay</Type>
</App>
</Apps>
所有 App 节点未能满足以上 2 个条件应在文件中 -> Mismatched.xml.
<Apps>
<App>
<AppID>715</AppID>
<Type>CP Pay</Type>
</App>
<App>
<AppID>725</AppID>
<Type>CP Pay</Type>
</App>
</Apps>
Java代码
public class Splitter {
public static void transform(String sourcePath, String xsltPath,
String resultDir) {
TransformerFactory tFactory = TransformerFactory.newInstance();
try {
Transformer transformer = tFactory.newTransformer(new StreamSource(
new File(xsltPath)));
transformer.transform(new StreamSource(new File(sourcePath)),
new StreamResult(new File(resultDir)));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// Set saxon as transformer.
System.setProperty("javax.xml.transform.TransformerFactory",
"net.sf.saxon.TransformerFactoryImpl");
String inputFilepath = "resources\InputFile.xml";
String transformXsltPath = "resources\Transform.xslt";
String outputDir = "D://Tmp//";
transform(inputFilepath, transformXsltPath, outputDir);
System.out.println("Completed");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="Apps">
<xsl:result-document href="MP.xml">
<xsl:copy>
<xsl:apply-templates select="App[contains(Type, 'MP')]"/>
</xsl:copy>
</xsl:result-document>
<xsl:result-document href="DP.xml">
<xsl:copy>
<xsl:apply-templates select="App[contains(Type, 'DP')]"/>
</xsl:copy>
</xsl:result-document>
<xsl:result-document href="Mismatched.xml">
<xsl:copy>
<xsl:apply-templates select="App[not(contains(Type, 'MP') or contains(Type, 'DP'))]"/>
</xsl:copy>
</xsl:result-document>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是一种更基于规则的方法:
<xsl:template match="App[starts-with(Type, 'MP')]" mode="group">MP</xsl:template>
<xsl:template match="App[starts-with(Type, 'DP')]" mode="group">DP</xsl:template>
<xsl:template match="App" mode="group">Mismatched</xsl:template>
<xsl:function name="f:key" as="xs:string">
<xsl:param name="e" as="element(App)"/>
<xsl:apply-templates select="." mode="group"/>
</xsl:function>
<xsl:template match="Apps">
<xsl:for-each-group select="App" group-by="f:key(.)">
<xsl:result-document href="{current-grouping-key()}.xml">
<Apps>
<xsl:copy-of select="current-group()"/>
</Apps>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
我有一个 XML 文件,需要根据 Xpath 变量上的匹配项(包含)进行拆分。
`<Apps>
<App>
<AppID>49O</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>715</AppID>
<Type>DP Pay</Type>
</App>
<App>
<AppID>716</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>725</AppID>
<Type>CP Pay</Type>
</App>
<App>
<AppID>728</AppID>
<Type>MP Pay</Type>
</App>
<App>
<AppID>728</AppID>
<Type>CP Pay</Type>
</App>
</Apps>`
所以拆分 xml 的条件是 1. Apps/App/Type/text()->包含'MP' 2. Apps/App/Type/text()->包含'DP'
以下是预期输出:
所有包含 Type 为 'MP' 的 App 节点都应该在一个文件中 -> MP.xml.
<Apps> <App> <AppID>49O</AppID> <Type>MP Pay</Type> </App> <App> <AppID>716</AppID> <Type>MP Pay</Type> </App> <App> <AppID>728</AppID> <Type>MP Pay</Type> </App> </Apps>
所有包含 Type 为 'DP' 的 App 节点都应该在一个文件中 -> DP.xml.
<Apps> <App> <AppID>715</AppID> <Type>DP Pay</Type> </App> </Apps>
所有 App 节点未能满足以上 2 个条件应在文件中 -> Mismatched.xml.
<Apps> <App> <AppID>715</AppID> <Type>CP Pay</Type> </App> <App> <AppID>725</AppID> <Type>CP Pay</Type> </App> </Apps>
Java代码
public class Splitter {
public static void transform(String sourcePath, String xsltPath,
String resultDir) {
TransformerFactory tFactory = TransformerFactory.newInstance();
try {
Transformer transformer = tFactory.newTransformer(new StreamSource(
new File(xsltPath)));
transformer.transform(new StreamSource(new File(sourcePath)),
new StreamResult(new File(resultDir)));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// Set saxon as transformer.
System.setProperty("javax.xml.transform.TransformerFactory",
"net.sf.saxon.TransformerFactoryImpl");
String inputFilepath = "resources\InputFile.xml";
String transformXsltPath = "resources\Transform.xslt";
String outputDir = "D://Tmp//";
transform(inputFilepath, transformXsltPath, outputDir);
System.out.println("Completed");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="Apps">
<xsl:result-document href="MP.xml">
<xsl:copy>
<xsl:apply-templates select="App[contains(Type, 'MP')]"/>
</xsl:copy>
</xsl:result-document>
<xsl:result-document href="DP.xml">
<xsl:copy>
<xsl:apply-templates select="App[contains(Type, 'DP')]"/>
</xsl:copy>
</xsl:result-document>
<xsl:result-document href="Mismatched.xml">
<xsl:copy>
<xsl:apply-templates select="App[not(contains(Type, 'MP') or contains(Type, 'DP'))]"/>
</xsl:copy>
</xsl:result-document>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是一种更基于规则的方法:
<xsl:template match="App[starts-with(Type, 'MP')]" mode="group">MP</xsl:template>
<xsl:template match="App[starts-with(Type, 'DP')]" mode="group">DP</xsl:template>
<xsl:template match="App" mode="group">Mismatched</xsl:template>
<xsl:function name="f:key" as="xs:string">
<xsl:param name="e" as="element(App)"/>
<xsl:apply-templates select="." mode="group"/>
</xsl:function>
<xsl:template match="Apps">
<xsl:for-each-group select="App" group-by="f:key(.)">
<xsl:result-document href="{current-grouping-key()}.xml">
<Apps>
<xsl:copy-of select="current-group()"/>
</Apps>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>