使用第二个xml文件中的数据向xml节点添加值(合并)

使用第二个xml文件中的数据向xml节点添加值(合并),xml,xslt,xslt-1.0,Xml,Xslt,Xslt 1.0,从今天早上开始,我一直在尝试使用xslt在xml文件中添加值。 基本上我有一个xml文件1.xml <?xml version="1.0" encoding="UTF-8"?> <Orderfile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <order> <establishmenthour>10:38:00</ establishmenthour> &

从今天早上开始,我一直在尝试使用xslt在xml文件中添加值。 基本上我有一个xml文件1.xml

<?xml version="1.0" encoding="UTF-8"?>
<Orderfile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  <order>
    <establishmenthour>10:38:00</ establishmenthour>
    <ExpirationDate/>
    <acc/>
    <identification>170610009-01</identification>
  </order>
  <order>
    <establishmenthour>10:40:00</ establishmenthour>
    <ExpirationDate/>
    <acc/>
    <identification>170610910-03</identification>
  </order>
  <order>
    <establishmenthour>10:42:00</ establishmenthour>
    <ExpirationDate/>
    <acc/>
    <identification>170610015-01</identification>
  </order>


以下是使用XSLT 2.0解决此问题的方法,使用
未解析文本
读入并
标记化
解析文本文件中的数据:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:param name="text-uri" select="'input.txt'"/>
    <xsl:param name="lines" select="tokenize(unparsed-text($text-uri), '\r?\n')"/>
    <xsl:param name="data" select="for $line in $lines return tokenize($line, ';')"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="order[id = $data[position() mod 2 = 1]]/ExpirationDate">
        <xsl:copy>
            <xsl:value-of select="$data[index-of($data, current()/../id) + 1]"/>
        </xsl:copy>     
    </xsl:template>

</xsl:stylesheet>

XSLT2.0受到各种工具(如oXygen、Stylus Studio、Altova XMLSpy)和独立处理器(如Saxon 9、XmlPrime、Exselt)的支持

现在,您已经将问题改为使用两个XML输入文档,可以使用XSLT 1.0,如下所示:

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

    <xsl:param name="data-uri" select="'input2.xml'"/>
    <xsl:param name="data-doc" select="document($data-uri)"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ExpirationDate">
        <xsl:copy>
            <xsl:variable name="match" select="$data-doc//order[identification = current()/../identification]/ExpirationDate"/>
            <xsl:choose>
                <xsl:when test="$match">
                    <xsl:value-of select="$match"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>     
    </xsl:template>

</xsl:stylesheet>

以下是使用XSLT 2.0解决此问题的方法,使用
未解析文本
读入并
标记化
解析文本文件中的数据:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:param name="text-uri" select="'input.txt'"/>
    <xsl:param name="lines" select="tokenize(unparsed-text($text-uri), '\r?\n')"/>
    <xsl:param name="data" select="for $line in $lines return tokenize($line, ';')"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="order[id = $data[position() mod 2 = 1]]/ExpirationDate">
        <xsl:copy>
            <xsl:value-of select="$data[index-of($data, current()/../id) + 1]"/>
        </xsl:copy>     
    </xsl:template>

</xsl:stylesheet>

XSLT2.0受到各种工具(如oXygen、Stylus Studio、Altova XMLSpy)和独立处理器(如Saxon 9、XmlPrime、Exselt)的支持

现在,您已经将问题改为使用两个XML输入文档,可以使用XSLT 1.0,如下所示:

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

    <xsl:param name="data-uri" select="'input2.xml'"/>
    <xsl:param name="data-doc" select="document($data-uri)"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ExpirationDate">
        <xsl:copy>
            <xsl:variable name="match" select="$data-doc//order[identification = current()/../identification]/ExpirationDate"/>
            <xsl:choose>
                <xsl:when test="$match">
                    <xsl:value-of select="$match"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>     
    </xsl:template>

</xsl:stylesheet>


事实上,这可能是第一步,如果我找到一种使用硬编码值的方法,我会意识到这是可以做到的。然后,我将使用bash脚本生成一个新的xslt(在修改值时复制过去)。您是否可以控制“texte”文件?如果那是一个XML文件,那就容易多了。在XSLT1.0中,可以使用
document
函数访问其他文件,但文件必须是XML。如果id是XML,那么匹配id也会更容易。
id(17061009-01)
正在计算
17061009
减去
01
,然后在结果上调用
id
函数,这样做毫无意义。此外,
id
函数仅适用于定义
id
属性的DTD。一般来说,最好转到XSLT2.0,在那里可以使用
未解析文本
读取文本文件,将正则表达式与
tokenize
和/或
xsl:analyze string
一起使用,然后根据需要匹配数据。查看此链接:我建议首先了解如何处理文本。你能在手之前把文本转换成格式良好的XML吗?然后这个规则就变得简单了。是的,我在文本文件上有一个控件,我将尝试在xml文件上转换它@MartinHonnen id用于我的示例,在实际中,该节点称为identification。是不是改变了什么。我从来没有使用过xslt 2.0,你有没有一个例子来告诉我它是如何工作的?事实上,这可能是第一步,如果我找到一种使用硬编码值的方法,我会意识到这是可以做到的。然后,我将使用bash脚本生成一个新的xslt(在修改值时复制过去)。您是否可以控制“texte”文件?如果那是一个XML文件,那就容易多了。在XSLT1.0中,可以使用
document
函数访问其他文件,但文件必须是XML。如果id是XML,那么匹配id也会更容易。
id(17061009-01)
正在计算
17061009
减去
01
,然后在结果上调用
id
函数,这样做毫无意义。此外,
id
函数仅适用于定义
id
属性的DTD。一般来说,最好转到XSLT2.0,在那里可以使用
未解析文本
读取文本文件,将正则表达式与
tokenize
和/或
xsl:analyze string
一起使用,然后根据需要匹配数据。查看此链接:我建议首先了解如何处理文本。你能在手之前把文本转换成格式良好的XML吗?然后这个规则就变得简单了。是的,我在文本文件上有一个控件,我将尝试在xml文件上转换它@MartinHonnen id用于我的示例,在实际中,该节点称为identification。是不是改变了什么。我从来没有使用过XSLT2.0,你有没有一个例子来告诉我它是如何工作的?谢谢你的回答,事实上我使用的是xmlstarlet,我认为它不适合XSLT2.0。也许我应该使用你的一种解决方案。马丁,你为什么要制作线条和数据参数?@Bluewood66,我本可以将它们改为变量,但为了灵活性,我使用了参数,因此,使用Java或.NET中的Saxon的应用程序可以选择传入文本文件uri或其他格式的数据,如字符串序列。@Martin Honnen。我以前见过,不太清楚为什么。谢谢你的回答。这很有帮助。@Rflow,由于您已更改为XML的输入格式,我添加了一个使用XSLT 1.0和
document
函数的解决方案。谢谢您的回答,事实上我使用的是xmlstarlet,我认为它不适用于XSLT 2.0。也许我应该使用你的一种解决方案。马丁,你为什么要制作线条和数据参数?@Bluewood66,我本可以将它们改为变量,但为了灵活性,我使用了参数,因此,使用Java或.NET中的Saxon的应用程序可以选择传入文本文件uri或其他格式的数据,如字符串序列。@Martin Honnen。我以前见过,不太清楚为什么。谢谢你的回答。这很有帮助。@Rflow,当您更改为XML的输入格式时,我添加了一个使用XSLT 1.0和
document
函数的解决方案。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:param name="data-uri" select="'input2.xml'"/>
    <xsl:param name="data-doc" select="document($data-uri)"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ExpirationDate">
        <xsl:copy>
            <xsl:variable name="match" select="$data-doc//order[identification = current()/../identification]/ExpirationDate"/>
            <xsl:choose>
                <xsl:when test="$match">
                    <xsl:value-of select="$match"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>     
    </xsl:template>

</xsl:stylesheet>