【问题标题】:Include xml from another file with contents from parent file包含来自另一个文件的 xml 和来自父文件的内容
【发布时间】:2021-03-13 18:01:36
【问题描述】:

是否可以将另一个 xml 文件(子 xml)的内容插入到具有更新属性的父 xml 中——严格使用 xml 或 xslt?还是我必须使用python来生成xml。

例如,假设我有一个包含内容的父 xml:

<root>
    <parent1 value="parent1">
        # get contents of child.xml
    </parent1>
    <parent2 value="parent2">
        # get contents of child.xml
    </parent2>
</root>

child.xml 有内容:

<root>
    <child1 value="child1"/>
    <child2 value="child2"/>
</root>

我可以用包含来做,但我也想更新值。所以我想要的最终xml是:

<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>

子项的值根据父项值更新。

【问题讨论】:

    标签: xml xslt dtd


    【解决方案1】:

    您可以使用document() 函数加载“子”文档并将其分配给样式表中的变量,然后与“父”内容混合:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
        
        <xsl:variable name="child-doc" select="document('child.xml')"/>
        
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        
        <xsl:template match="/root/*">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates select="$child-doc/root/*" mode="child">
                    <xsl:with-param name="prefix" tunnel="yes" select="@value"/>
                </xsl:apply-templates>
            </xsl:copy>
        </xsl:template>
        
        <xsl:template match="@*|node()" mode="child">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" mode="child"/>
            </xsl:copy>
        </xsl:template>
        
        <xsl:template match="root/*/@value" mode="child">
            <xsl:param name="prefix" tunnel="yes"/>
            <xsl:attribute name="value" select="string-join(($prefix, .), '_')"/>
        </xsl:template>
        
    </xsl:stylesheet>
    

    【讨论】:

      【解决方案2】:

      您可以使用 document() 函数来引用另一个 XML 文件。你可以这样实现。

      <?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:template match="@*|node()">
          <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
          </xsl:copy>
        </xsl:template>
        
        <xsl:template match="parent">
          <xsl:variable name="currentParent" select="."/>
          <xsl:copy>
            <xsl:for-each select="$childDoc/root/child">
              <xsl:copy>
                <xsl:attribute name="value" select="concat($currentParent/@value,'_',@value)"/>
              </xsl:copy>
            </xsl:for-each>
          </xsl:copy>
        </xsl:template>
        
      </xsl:stylesheet>
      

      在这里看到它的工作:https://xsltfiddle.liberty-development.net/pNvtBGr (出于测试目的,我已将文档放入变量中。)

      【讨论】:

      • 感谢您的解决方案。这确实适用于您的示例,但父级并不总是父级,它可能是 parent1、parent2、something1、something2 等。如何更新解决方案以使用可变父标签?
      • 您的模板需要匹配某个名称。元素名称的第一部分是否始终相同?一种方法是使用 match="parent1 | parent2 | something1 | something2" 但如果您有无限数量的元素名称,这将不起作用。
      • 可能会有大约 20 个值,但绝对比将所有子元素重复 20 次要好
      猜你喜欢
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 2021-11-04
      • 2014-03-17
      • 2012-11-18
      • 1970-01-01
      • 2011-11-26
      相关资源
      最近更新 更多