在 XSLT 中查询数据库并将结果应用于输出 XML
Querying database inside XSLT to and apply the result to output XML
我需要根据 ProductItemId 查询数据库并获取以下 XML 的 ProductName、ProductItemCode、ProductType 和 ActCode。我正在使用 SaxonEE 进行转换。查询应在 XSLT
内部触发
我的输入XML是:
<?xml version="1.0" encoding="UTF-8"?>
<ListOfSublines>
<OrderSubline>
<OrderSublineNumber>1</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>120</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>10</ProductItemId>
<AdditionalParams>
<Parameter name="LOC_CODE" value="25"/>
<Parameter name="LOC_DESC" value="Kolkata Circle"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>2</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>121</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>11</ProductItemId>
<AdditionalParams>
<Parameter name="PRODUCT_INDICATOR" value="Mobility Voice"/>
<Parameter name="RATE CLASS" value="1"/>
<Parameter name="RRCC" value="Bharti Tele-Ventures"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>3</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>122</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>12</ProductItemId>
<AdditionalParams/>
</ProductItem>
</OrderSubline>
</ListOfSublines>
预期输出:
<?xml version="1.0" encoding="UTF-8"?>
<ListOfSublines>
<OrderSubline>
<OrderSublineNumber>1</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>120</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>10</ProductItemId>
<ProductName>Value from Oracle Db based on ProductItemId 10</ProductName>
<ProductItemCode>Value from Oracle Db</ProductItemCode>
<ProductType>Value from Oracle Db</ProductType>
<ActCode>Value from Oracle Db</ActCode>
<AdditionalParams>
<Parameter name="LOC_CODE" value="25"/>
<Parameter name="LOC_DESC" value="Kolkata Circle"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>2</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>121</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>11</ProductItemId>
<ProductName>Value from Oracle Db based on ProductItemId 11</ProductName>
<ProductItemCode>Value from Oracle Db</ProductItemCode>
<ProductType>Value from Oracle Db</ProductType>
<ActCode>Value from Oracle Db</ActCode>
<AdditionalParams>
<Parameter name="PRODUCT_INDICATOR" value="Mobility Voice"/>
<Parameter name="RATE CLASS" value="1"/>
<Parameter name="RRCC" value="Bharti Tele-Ventures"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>3</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>122</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>12</ProductItemId>
<ProductName>Value from Oracle Db based on ProductItemId 12</ProductName>
<ProductItemCode>Value from Oracle Db</ProductItemCode>
<ProductType>Value from Oracle Db</ProductType>
<ActCode>Value from Oracle Db</ActCode>
<AdditionalParams/>
</ProductItem>
</OrderSubline>
</ListOfSublines>
您可以使用 Saxon 的 SQL 扩展(它完成了 80% 的人需要的 20% 的功能,但绝不是完整的),或者您可以使用 Java 扩展机制。
SQL 和 XSLT 都是 special-purpose 语言(共享声明类型的特征),旨在做一件特定的事情。对于 SQL 这通常意味着数据库操作或检索或 DDL and DML 过程,对于 XSLT 这意味着操作 XML 文档。
考虑使用通用语言,例如 Java(一种 Oracle 产品)、C#、Python、PHP、Perl、VB 甚至 R 和 SAS 以及还有一些可以处理您的 Oracle 数据库检索需求和 XML 文档解析和操作。此外,上述这些语言和其他语言为 XSLT 1.0 处理器维护它们自己的库,包括 XPath 1.0 和 XML DOM 文档库。更重要的是,这些语言可以通过命令行(线程或子进程)调用外部可执行文件,例如 Saxon EE,传递所需的参数,例如 xml 或 xslt 文档路径。最后,这些相同的语言维护 SQL ODBC/OLEDB api 库,包括 Oracle 数据库。顺便说一句,Oracle 在其 PL/SQL 方言中维护(与其他企业级 RDMS -SQL 服务器、PostgreSQL 一样)自己的 XML manipulation syntax and features。
总而言之,根据您的需要,请考虑以下步骤:
- 选择熟悉的通用语言(上述或其他);
- 安装其必需的 Oracle 数据库连接器 API(即 Java 的 JDBC
driver,
Python 的 cx_Oracle、PHP 的
PDO DSN);
- 查询数据库 select 数据 SQL;
- 遍历查询数据以动态创建输入 XML 文档;
- 运行 XSLT 具有通用编码或最终 XML 输出的外部可执行文件;
感谢@Michael 的提示,我尝试了 SAXON SQL 扩展并能够查询数据库。
这是对我来说工作正常的 XSLT 代码:
<xsl:transform version="2.0"
exclude-result-prefixes="java saxon xsd xsi xsl"
extension-element-prefixes="saxon sql"
xmlns:java="http://saxon.sf.net/java-type"
xmlns:saxon="http://saxon.sf.net/"
xmlns:sql="java://net.sf.saxon.sql.SQLElementFactory"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:variable name="count" select="0" saxon:assignable="yes"/>
<xsl:output method="xml" indent="yes"/>
<xsl:preserve-space elements="*" />
<xsl:param name="jdbc.driver" as="xsd:string" select="'com.mysql.jdbc.Driver'" />
<xsl:param name="jdbc.database" as="xsd:string" select="'jdbc:mysql://localhost:3306/test'" />
<xsl:param name="jdbc.user" as="xsd:string" select="'root'" />
<xsl:param name="jdbc.pass" as="xsd:string" select="'root'" />
<xsl:template match="BOOKS">
<xsl:variable name="sql.conn" as="java:java.sql.Connection">
<sql:connect driver="{$jdbc.driver}" database="{$jdbc.database}" user="{$jdbc.user}" password="{$jdbc.pass}">
<xsl:fallback>
<xsl:message terminate="yes">SQL extenstions are not installed</xsl:message>
</xsl:fallback>
</sql:connect>
</xsl:variable>
<xsl:for-each select="ITEM">
<sql:insert connection="$sql.conn" table="book">
<sql:column name="title" select="TITLE"/>
<sql:column name="author" select="AUTHOR"/>
<sql:column name="category" select="@CAT"/>
</sql:insert>
<saxon:assign name="count" select="$count+1"/>
</xsl:for-each>
<xsl:variable name="book-table">
<sql:query connection="$sql.conn" table="book" column="*" row-tag="book" column-tag="col"/>
</xsl:variable>
<xsl:message>There are now <xsl:value-of select="count($book-table//book)"/> books.</xsl:message>
<new-book-table>
<xsl:copy-of select="$book-table"/>
</new-book-table>
</xsl:template>
</xsl:transform>
希望对其他人有所帮助。
我需要根据 ProductItemId 查询数据库并获取以下 XML 的 ProductName、ProductItemCode、ProductType 和 ActCode。我正在使用 SaxonEE 进行转换。查询应在 XSLT
内部触发我的输入XML是:
<?xml version="1.0" encoding="UTF-8"?>
<ListOfSublines>
<OrderSubline>
<OrderSublineNumber>1</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>120</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>10</ProductItemId>
<AdditionalParams>
<Parameter name="LOC_CODE" value="25"/>
<Parameter name="LOC_DESC" value="Kolkata Circle"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>2</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>121</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>11</ProductItemId>
<AdditionalParams>
<Parameter name="PRODUCT_INDICATOR" value="Mobility Voice"/>
<Parameter name="RATE CLASS" value="1"/>
<Parameter name="RRCC" value="Bharti Tele-Ventures"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>3</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>122</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>12</ProductItemId>
<AdditionalParams/>
</ProductItem>
</OrderSubline>
</ListOfSublines>
预期输出:
<?xml version="1.0" encoding="UTF-8"?>
<ListOfSublines>
<OrderSubline>
<OrderSublineNumber>1</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>120</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>10</ProductItemId>
<ProductName>Value from Oracle Db based on ProductItemId 10</ProductName>
<ProductItemCode>Value from Oracle Db</ProductItemCode>
<ProductType>Value from Oracle Db</ProductType>
<ActCode>Value from Oracle Db</ActCode>
<AdditionalParams>
<Parameter name="LOC_CODE" value="25"/>
<Parameter name="LOC_DESC" value="Kolkata Circle"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>2</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>121</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>11</ProductItemId>
<ProductName>Value from Oracle Db based on ProductItemId 11</ProductName>
<ProductItemCode>Value from Oracle Db</ProductItemCode>
<ProductType>Value from Oracle Db</ProductType>
<ActCode>Value from Oracle Db</ActCode>
<AdditionalParams>
<Parameter name="PRODUCT_INDICATOR" value="Mobility Voice"/>
<Parameter name="RATE CLASS" value="1"/>
<Parameter name="RRCC" value="Bharti Tele-Ventures"/>
</AdditionalParams>
</ProductItem>
</OrderSubline>
<OrderSubline>
<OrderSublineNumber>3</OrderSublineNumber>
<OrderSublineType>ADD</OrderSublineType>
<OrderlineInstance>122</OrderlineInstance>
<Lob/>
<Circle/>
<Zone/>
<ProductItem>
<ProductItemId>12</ProductItemId>
<ProductName>Value from Oracle Db based on ProductItemId 12</ProductName>
<ProductItemCode>Value from Oracle Db</ProductItemCode>
<ProductType>Value from Oracle Db</ProductType>
<ActCode>Value from Oracle Db</ActCode>
<AdditionalParams/>
</ProductItem>
</OrderSubline>
</ListOfSublines>
您可以使用 Saxon 的 SQL 扩展(它完成了 80% 的人需要的 20% 的功能,但绝不是完整的),或者您可以使用 Java 扩展机制。
SQL 和 XSLT 都是 special-purpose 语言(共享声明类型的特征),旨在做一件特定的事情。对于 SQL 这通常意味着数据库操作或检索或 DDL and DML 过程,对于 XSLT 这意味着操作 XML 文档。
考虑使用通用语言,例如 Java(一种 Oracle 产品)、C#、Python、PHP、Perl、VB 甚至 R 和 SAS 以及还有一些可以处理您的 Oracle 数据库检索需求和 XML 文档解析和操作。此外,上述这些语言和其他语言为 XSLT 1.0 处理器维护它们自己的库,包括 XPath 1.0 和 XML DOM 文档库。更重要的是,这些语言可以通过命令行(线程或子进程)调用外部可执行文件,例如 Saxon EE,传递所需的参数,例如 xml 或 xslt 文档路径。最后,这些相同的语言维护 SQL ODBC/OLEDB api 库,包括 Oracle 数据库。顺便说一句,Oracle 在其 PL/SQL 方言中维护(与其他企业级 RDMS -SQL 服务器、PostgreSQL 一样)自己的 XML manipulation syntax and features。
总而言之,根据您的需要,请考虑以下步骤:
- 选择熟悉的通用语言(上述或其他);
- 安装其必需的 Oracle 数据库连接器 API(即 Java 的 JDBC driver, Python 的 cx_Oracle、PHP 的 PDO DSN);
- 查询数据库 select 数据 SQL;
- 遍历查询数据以动态创建输入 XML 文档;
- 运行 XSLT 具有通用编码或最终 XML 输出的外部可执行文件;
感谢@Michael 的提示,我尝试了 SAXON SQL 扩展并能够查询数据库。
这是对我来说工作正常的 XSLT 代码:
<xsl:transform version="2.0"
exclude-result-prefixes="java saxon xsd xsi xsl"
extension-element-prefixes="saxon sql"
xmlns:java="http://saxon.sf.net/java-type"
xmlns:saxon="http://saxon.sf.net/"
xmlns:sql="java://net.sf.saxon.sql.SQLElementFactory"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:variable name="count" select="0" saxon:assignable="yes"/>
<xsl:output method="xml" indent="yes"/>
<xsl:preserve-space elements="*" />
<xsl:param name="jdbc.driver" as="xsd:string" select="'com.mysql.jdbc.Driver'" />
<xsl:param name="jdbc.database" as="xsd:string" select="'jdbc:mysql://localhost:3306/test'" />
<xsl:param name="jdbc.user" as="xsd:string" select="'root'" />
<xsl:param name="jdbc.pass" as="xsd:string" select="'root'" />
<xsl:template match="BOOKS">
<xsl:variable name="sql.conn" as="java:java.sql.Connection">
<sql:connect driver="{$jdbc.driver}" database="{$jdbc.database}" user="{$jdbc.user}" password="{$jdbc.pass}">
<xsl:fallback>
<xsl:message terminate="yes">SQL extenstions are not installed</xsl:message>
</xsl:fallback>
</sql:connect>
</xsl:variable>
<xsl:for-each select="ITEM">
<sql:insert connection="$sql.conn" table="book">
<sql:column name="title" select="TITLE"/>
<sql:column name="author" select="AUTHOR"/>
<sql:column name="category" select="@CAT"/>
</sql:insert>
<saxon:assign name="count" select="$count+1"/>
</xsl:for-each>
<xsl:variable name="book-table">
<sql:query connection="$sql.conn" table="book" column="*" row-tag="book" column-tag="col"/>
</xsl:variable>
<xsl:message>There are now <xsl:value-of select="count($book-table//book)"/> books.</xsl:message>
<new-book-table>
<xsl:copy-of select="$book-table"/>
</new-book-table>
</xsl:template>
</xsl:transform>
希望对其他人有所帮助。