【问题标题】:Python: Generate xml using xml & xslt filePython:使用 xml 和 xslt 文件生成 xml
【发布时间】:2021-03-21 07:37:04
【问题描述】:

我想使用输入 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>

问题是该站点使用的是撒克逊引擎,我认为这可能需要许可证。我想使用 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版本?这里有一些 cmets 如何使用 saxon use saxon with python,但我想防止需要 java 或其他外部应用程序。有没有办法只用 python 来完成上述工作?或者有没有办法更新我的 xslt 文件,以便它只使用 lxml 转换函数?

【问题讨论】:

  • childDoc 节点实际上在哪里?它们是在单独的 XML 文档中,还是在 XSLT 中列出?它在 XSLT 1.0 中有所作为。
  • 目前 childDoc 只是在 xslt 本身中列出

标签: python xml xslt lxml saxon


【解决方案1】:

Saxon-C 1.2.1 是最新版本的 Saxon-C https://www.saxonica.com/saxon-c/index.xml 并具有 Python API https://www.saxonica.com/saxon-c/doc/html/saxonc.html,因此您可以下载 https://www.saxonica.com/download/c.xml,安装 https://www.saxonica.com/saxon-c/documentation/index.html#!starting/installing 并从 Python 运行 https://www.saxonica.com/saxon-c/documentation/index.html#!samples/samples_python认为您需要使用 XSLT 3。

HE 版不需要您购买许可证。

至于 XSLT 中的错误,如果您想使用 xsltfiddle 测试 XSLT 1.0 代码,则选择 XslCompiledTransform 作为 XSLT 处理器,如果您确实声明了变量值,您的代码和最简单的方法会出现类似错误inline 作为结果树片段,就是使用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>

https://xsltfiddle.liberty-development.net/aiyned/3

【讨论】:

  • 感谢您的回复。是的,我宁愿不安装其他依赖项,但我很欣赏您提供的步骤,以防我想安装 saxon。使用上面的更新 xsl,可以像您所说的那样使用 lxml 正确读取它,但结果不再相同。有没有办法将值更新为“parentX_childX”等
  • 查看编辑,但请记住,使用 &lt;xsl:variable name="childDoc" select="document('child.xml')"/&gt; 将为您节省所有结果树 -> 原始样本产生的节点集转换麻烦。
  • 非常感谢,这对我有帮助!
猜你喜欢
  • 2013-08-13
  • 2010-09-24
  • 2017-05-09
  • 2014-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多