如何使用XSLT中第二个xml输入的变量修改一个xml输入?

时间:2016-03-17 12:41:48

标签: xslt xslt-2.0

我的问题是如何更改< color>中的值在sample1.xml中基于相同的< id>在sample2.xml中

sample1.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <item>
        <id>1</id>
        <color>red</color>
    </item>
    <item>
        <id>2</id>
        <color>blue</color>
    </item>
    <item>
        <id>3</id>
        <color>green></color>
    </item>
</root>

示例2.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <item>
      <id>1</id>
      <color>yellow</color>
   </item>
   <item>
      <id>3</id>
      <color>white</color>
   </item>
</root>

预期产出

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <item>
        <id>1</id>
        <color>yellow</color>
    </item>
    <item>
        <id>2</id>
        <color>blue</color>
    </item>
    <item>
        <id>3</id>
        <color>white></color>
    </item>
</root>

我只知道如何将整个sample1.xml复制到输出中,但我不知道如何记住sample2.xml中的id,并且通过该值对sample1进行更改。 不知道是否可能,但我可能必须以某种未知的方式使用变量。

这是我的代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs" xmlns:saxon="http://saxon.sf.net/" extension-element-prefixes="saxon"
version="2.0">

    <xsl:output method="xml" indent="yes" media-type="text/xml" />

    <xsl:param name="sample1"/>
    <xsl:param name="sample1_xml" select="saxon:parse($sample1)"/>

    <xsl:param name="sample2"/>
    <xsl:param name="sample2_xml" select="saxon:parse($sample2)"/>

    <xsl:template match="/" name="initial">
        <xsl:apply-templates select="$sample1_xml/node()"/> <!-- this is only for copying entire sample1 file -->

    </xsl:template>

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

    </xsl:template>
</xsl:stylesheet>

我真的不知道这样做的正确方法是什么,因为我是XSLT 2.0的新手。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

定义键<xsl:key name="id" match="item" use="id"/>,然后添加模板

<xsl:template match="item[key('id', id, $sample2_xml)]/color">
  <xsl:copy-of select="key('id', ../id, $sample2_xml)/color"/>
</xsl:template>

所以完整的样本是

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

    <xsl:output method="xml" indent="yes" media-type="text/xml" />

    <xsl:param name="sample1" as="xs:string"><![CDATA[<root>
    <item>
        <id>1</id>
        <color>red</color>
    </item>
    <item>
        <id>2</id>
        <color>blue</color>
    </item>
    <item>
        <id>3</id>
        <color>green></color>
    </item>
</root>]]></xsl:param>
    <xsl:param name="sample1_xml" select="saxon:parse($sample1)"/>

    <xsl:param name="sample2" as="xs:string"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<root>
   <item>
      <id>1</id>
      <color>yellow</color>
   </item>
   <item>
      <id>3</id>
      <color>white</color>
   </item>
</root>]]></xsl:param>


    <xsl:param name="sample2_xml" select="saxon:parse($sample2)"/>

    <xsl:key name="id" match="item" use="id"/>

    <xsl:template match="/" name="initial">
        <xsl:apply-templates select="$sample1_xml/node()"/> <!-- this is only for copying entire sample1 file -->

    </xsl:template>

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

    </xsl:template>

    <xsl:template match="item[key('id', id, $sample2_xml)]/color">
        <xsl:copy-of select="key('id', ../id, $sample2_xml)/color"/>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

我被Martin Honnen打败了,但这是我的解决方案:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            exclude-result-prefixes="xs" xmlns:saxon="http://saxon.sf.net/" extension-element-prefixes="saxon"
            version="2.0">

<xsl:output method="xml" indent="yes" media-type="text/xml"/>

<xsl:param name="sample1"/>
<xsl:param name="sample1_xml" select="saxon:parse($sample1)"/>

<xsl:param name="sample2"/>
<xsl:param name="sample2_xml" select="saxon:parse($sample2)"/>

<xsl:template match="/" name="initial">
    <xsl:apply-templates select="$sample1_xml/node()"/>
    <!-- this is only for copying entire sample1 file -->

</xsl:template>

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

<xsl:template match="/root/item/color">
    <xsl:param name="id" select="parent::item/id/text()"/>
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="$sample2_xml/root/item[id=$id]/color">
                <xsl:value-of select="$sample2_xml/root/item[id=$id]/color/text()"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="text()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>