xml - 用该元素的多个副本替换 XML 元素

标签 xml xslt

我有一个包含类似元素的 XML 文件

  <function name="negate" arg1="multivector"/>

我想转换这些元素,以便 multivector 被 8 个东西中的每一个替换,包括 vectorbivectorrotor 等。因此转换后的 XML 将具有 8 个 negate 元素:

  <function name="negate" arg1="multivector"/>
  <function name="negate" arg1="multivector3"/>
  <function name="negate" arg1="vector"/>
  <function name="negate" arg1="vector3"/>
  <function name="negate" arg1="vector"/>
  <function name="negate" arg1="bivector3"/>
  <function name="negate" arg1="rotor"/>
  <function name="negate" arg1="rotor3"/>

同样,我的元素有两种arg:

  <function name="add" arg1="multivector" arg2="multivector"/>

转换后的 XML 应该有 64 个 add 元素,其中 args 是 vector 的各种组合,等等,尽管我会免去我们写这些的所有痛苦明确地。

我可以弄清楚如何将 multivector 转换为我的任何一个新事物,但我不太清楚如何让它多次复制同一事物。我必须手动进行丑陋的更换吗?我可以优雅地自动循环所有 8 或 64 个东西吗?


我的基本第一步

以下是我到目前为止所得到的,但它只是做了最基本的事情,将每个 arg2="multivector" 属性替换为 arg2="vector"。也欢迎对一般样式进行改进,因为我是 XML 的新手。

<?xml version="1.0" encoding="UTF-8"?>

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- Find any arg2="multivector" attribute and replace -->
  <xsl:template match="function[@arg2='multivector']/@arg2">
    <xsl:attribute name="arg2">vector</xsl:attribute>
  </xsl:template>

  <!-- Just copy anything that didn't match above -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:transform>

最佳答案

我假设您有一些这样的输入数据:

<functions>
    <function name="xxxxx" arg1="yyyyy" />
    <function name="negate" arg1="multivector"/>
    <function name="negate" arg1="zzzzz" />
    <function name="add" arg1="multivector" arg2="multivector"/>
    <function name="add" arg1="aaaaa" arg2="bbbbb" />
    <function name="add" arg1="ccccc" arg2="ddddd" />
</functions>

并且您想生成一个新的 XML,保留所有现有元素,除了具有以下格式的元素:

<function name="negate" arg1="multivector"/>

<function name="add" arg1="multivector" arg2="multivector"/>

您希望将它们替换为 n <function name="negate" arg1="..."/>元素和 n*n <function name="add" arg1="..." arg2="..."/> ,同时保留 <function name="xxxxx" arg1="yyyyy" /> 等元素和 <function name="negate" arg1="zzzzz" />他们在哪里。

您可以将要用于 args 的数据放在一个单独的文件中(您也可以将它放在 XSL 文件中,为其定义一个本地命名空间)。我将使用一个包含三个元素的元素:

<?xml version="1.0" encoding="UTF-8"?>
<vectors>
    <vector>vector</vector>
    <vector>bivector</vector>
    <vector>rotor</vector>
</vectors>

我将此文件称为 vectors.xml .

然后将该文件读入 XSLT 样式表,存储 vector变量中的节点集,遍历每个元素两次并生成所有组合。您还将输入文档函数存储在一个变量中,因此您可以复制不受影响的节点。

这是样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:variable name="vectors" select="document('vectors.xml')/vectors"/>
    <xsl:variable name="functions" select="/functions"/>

    <xsl:template match="functions">
        <xsl:copy>
            <xsl:apply-templates select="$vectors/vector"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="vector">
        <xsl:variable name="arg1" select="."/>
        <xsl:for-each select="$functions/function">
            <xsl:choose>
                <xsl:when test="@name='negate' and @arg1='multivector'">
                    <function name="negate" arg1="{$arg1}"/>
                </xsl:when>
                <xsl:when test="@name='add' and @arg1='multivector' and @arg2='multivector'">
                    <xsl:for-each select="$vectors/vector">
                        <function name="add" arg1="{$arg1}" arg2="{.}"/>
                    </xsl:for-each>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

使用 functions文件包含上面列出的数据作为输入,并具有 vectors.xml文件也在上面列出的同一目录中,它将生成:

<functions>
   <function name="something" arg1="something"/>
   <function name="negate" arg1="vector"/>
   <function name="negate" arg1="kkk"/>
   <function name="add" arg1="vector" arg2="vector"/>
   <function name="add" arg1="vector" arg2="bivector"/>
   <function name="add" arg1="vector" arg2="rotor"/>
   <function name="add" arg1="abc" arg2="xyz"/>
   <function name="add" arg1="xyz" arg2="xyz"/>
   <function name="something" arg1="something"/>
   <function name="negate" arg1="bivector"/>
   <function name="negate" arg1="kkk"/>
   <function name="add" arg1="bivector" arg2="vector"/>
   <function name="add" arg1="bivector" arg2="bivector"/>
   <function name="add" arg1="bivector" arg2="rotor"/>
   <function name="add" arg1="abc" arg2="xyz"/>
   <function name="add" arg1="xyz" arg2="xyz"/>
   <function name="something" arg1="something"/>
   <function name="negate" arg1="rotor"/>
   <function name="negate" arg1="kkk"/>
   <function name="add" arg1="rotor" arg2="vector"/>
   <function name="add" arg1="rotor" arg2="bivector"/>
   <function name="add" arg1="rotor" arg2="rotor"/>
   <function name="add" arg1="abc" arg2="xyz"/>
   <function name="add" arg1="xyz" arg2="xyz"/>
</functions>

关于xml - 用该元素的多个副本替换 XML 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22204763/

相关文章:

javascript - 如何从 Node Sax 中的 XML 文件读取 CDATA

xml - SQL Server XML 替换属性中的值

xml - XSLT:选择跟随兄弟直到到达指定的标签

XSLT 1.0 : how to go for the "parent" axis

android - 坚持使用 xmlpullparser 读取 Xml

java - 我怎样才能改变我的 ListView 的字体颜色和字体类型

java - 使用 Resources.getSystem() 从 .xml 获取 Android 中的字符串数组

xslt - XSL xsl :evaluate multiple nodes

xml - 使用XPath从XML获取特定节点

xml - Docbook XML 到 PDF,没有 'ő' 和 'ű' 字符