Python:使用 xml & xslt 文件生成 xml
Python: Generate xml using xml & xslt file
我想使用输入 xml 和 xslt 文件生成 xml。我在此处有示例输入 xml 和 xslt 文件 <https://xsltfiddle.liberty-development.net/aiyned/1>。最后的输出是我想要的。
基本上 input.xml 是:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<parent1 value="parent1">
<inserthere value="parent1"/>
</parent1>
<parent2 value="parent2">
<inserthere value="parent2"/>
</parent2>
</root>
input.xslt 是:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml"/>
<!-- <xsl:variable name="childDoc" select="document('child.xml')"/> -->
<xsl:variable name="childDoc">
<root>
<child1 value="child1"/>
<child2 value="child2"/>
</root>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="inserthere">
<xsl:variable name="currentParent" select="."/>
<xsl:for-each select="$childDoc/root/node()">
<xsl:copy>
<xsl:attribute name="value" select="concat($currentParent/@value,'_',@value)"/>
</xsl:copy>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
输出xml是:
<?xml version="1.0" encoding="UTF-8"?><root>
<parent1 value="parent1">
<child1 value="parent1_child1"/>
<child2 value="parent1_child2"/>
</parent1>
<parent2 value="parent2">
<child1 value="parent2_child1"/>
<child2 value="parent2_child2"/>
</parent2>
</root>
问题是网站使用的是 saxon 引擎,我认为这可能需要许可证。我想使用 lxml 或任何免费的 python 库生成输出 xml。目前当我 运行
import lxml.etree as ET
dom = ET.parse("input.xml")
xslt = ET.parse("input.xslt")
transform = ET.XSLT(xslt)
newdom = transform(dom)
print(ET.tostring(newdom, pretty_print=True))
我得到一个错误:
newdom = transform(dom)
File "src/lxml/xslt.pxi", line 602, in lxml.etree.XSLT.__call__
lxml.etree.XSLTApplyError: Failed to evaluate the 'select' expression.
我觉得问题是lxml只支持1.0版本?这里有一些关于如何使用 saxon 的评论,但我想避免要求 java 或其他外部应用程序。有没有办法只用 python 就可以完成上述工作?或者有没有办法更新我的 xslt 文件,以便它只使用 lxml 转换函数?
如果您认为需要使用 XSLT 3,Saxon-C 1.2.1 是来自 Python 的 Saxon-C https://www.saxonica.com/saxon-c/index.xml and has a Python API https://www.saxonica.com/saxon-c/doc/html/saxonc.html so you can download https://www.saxonica.com/download/c.xml, install https://www.saxonica.com/saxon-c/documentation/index.html#!starting/installing and run it https://www.saxonica.com/saxon-c/documentation/index.html#!samples/samples_python 的最新版本。
HE 版本不需要您购买许可证。
至于 XSLT 中的错误,如果您想使用 xsltfiddle 测试 XSLT 1.0 代码,请选择 XslCompiledTransform 作为 XSLT 处理器,如果您真的声明了您的代码,您将得到类似的代码错误和最简单的方法变量值内联结果树片段,就是使用exsl:node-set
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:output method="xml"/>
<!-- <xsl:variable name="childDoc" select="document('child.xml')"/> -->
<xsl:variable name="childDoc">
<root>
<child1 value="child1"/>
<child2 value="child2"/>
</root>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="inserthere">
<xsl:variable name="currentParent" select="."/>
<xsl:copy-of select="exsl:node-set($childDoc)/root/node()"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/aiyned/4
或者,如果您想更改值,请使用模板
<xsl:template match="inserthere">
<xsl:variable name="currentParent" select="."/>
<xsl:for-each select="exsl:node-set($childDoc)/root/node()">
<xsl:copy>
<xsl:attribute name="value">
<xsl:value-of select="concat($currentParent/@value,'_',@value)"/>
</xsl:attribute>
</xsl:copy>
</xsl:for-each>
</xsl:template>
我想使用输入 xml 和 xslt 文件生成 xml。我在此处有示例输入 xml 和 xslt 文件 <https://xsltfiddle.liberty-development.net/aiyned/1>。最后的输出是我想要的。
基本上 input.xml 是:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<parent1 value="parent1">
<inserthere value="parent1"/>
</parent1>
<parent2 value="parent2">
<inserthere value="parent2"/>
</parent2>
</root>
input.xslt 是:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml"/>
<!-- <xsl:variable name="childDoc" select="document('child.xml')"/> -->
<xsl:variable name="childDoc">
<root>
<child1 value="child1"/>
<child2 value="child2"/>
</root>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="inserthere">
<xsl:variable name="currentParent" select="."/>
<xsl:for-each select="$childDoc/root/node()">
<xsl:copy>
<xsl:attribute name="value" select="concat($currentParent/@value,'_',@value)"/>
</xsl:copy>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
输出xml是:
<?xml version="1.0" encoding="UTF-8"?><root>
<parent1 value="parent1">
<child1 value="parent1_child1"/>
<child2 value="parent1_child2"/>
</parent1>
<parent2 value="parent2">
<child1 value="parent2_child1"/>
<child2 value="parent2_child2"/>
</parent2>
</root>
问题是网站使用的是 saxon 引擎,我认为这可能需要许可证。我想使用 lxml 或任何免费的 python 库生成输出 xml。目前当我 运行
import lxml.etree as ET
dom = ET.parse("input.xml")
xslt = ET.parse("input.xslt")
transform = ET.XSLT(xslt)
newdom = transform(dom)
print(ET.tostring(newdom, pretty_print=True))
我得到一个错误:
newdom = transform(dom)
File "src/lxml/xslt.pxi", line 602, in lxml.etree.XSLT.__call__
lxml.etree.XSLTApplyError: Failed to evaluate the 'select' expression.
我觉得问题是lxml只支持1.0版本?这里有一些关于如何使用 saxon
如果您认为需要使用 XSLT 3,Saxon-C 1.2.1 是来自 Python 的 Saxon-C https://www.saxonica.com/saxon-c/index.xml and has a Python API https://www.saxonica.com/saxon-c/doc/html/saxonc.html so you can download https://www.saxonica.com/download/c.xml, install https://www.saxonica.com/saxon-c/documentation/index.html#!starting/installing and run it https://www.saxonica.com/saxon-c/documentation/index.html#!samples/samples_python 的最新版本。
HE 版本不需要您购买许可证。
至于 XSLT 中的错误,如果您想使用 xsltfiddle 测试 XSLT 1.0 代码,请选择 XslCompiledTransform 作为 XSLT 处理器,如果您真的声明了您的代码,您将得到类似的代码错误和最简单的方法变量值内联结果树片段,就是使用exsl:node-set
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:output method="xml"/>
<!-- <xsl:variable name="childDoc" select="document('child.xml')"/> -->
<xsl:variable name="childDoc">
<root>
<child1 value="child1"/>
<child2 value="child2"/>
</root>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="inserthere">
<xsl:variable name="currentParent" select="."/>
<xsl:copy-of select="exsl:node-set($childDoc)/root/node()"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/aiyned/4
或者,如果您想更改值,请使用模板
<xsl:template match="inserthere">
<xsl:variable name="currentParent" select="."/>
<xsl:for-each select="exsl:node-set($childDoc)/root/node()">
<xsl:copy>
<xsl:attribute name="value">
<xsl:value-of select="concat($currentParent/@value,'_',@value)"/>
</xsl:attribute>
</xsl:copy>
</xsl:for-each>
</xsl:template>