比较节点值并根据与XSLT的比较写入另一个节点的值

时间:2014-08-18 23:23:38

标签: xml xslt

如果这看似迟钝或过于简单,我道歉。我当然不是XSLT的专家。

我有两个XML:

XML#1

<simpletable>

   <strow>
     <stentry props="part-name">This is a test</stentry>
     <stentry props="part-number">1008590-00-C</stentry>
   </strow>
   <strow>
     <stentry props="part-name">Another test</stentry>
     <stentry props="part-number">1008590-00-D</stentry>
   </strow>
   <strow>
     <stentry props="part-name">Still another test</stentry>
     <stentry props="part-number">1030348-00-A</stentry>
   </strow>

</simpletable>  

XML#2

<simpletable relcolwidth="5* 40* 15* 5* 35*">
           <sthead translate="yes">
              <stentry>No.</stentry>
              <stentry>Part Description</stentry>
              <stentry>Part Number</stentry>
              <stentry>Qty</stentry>
              <stentry>Comments</stentry>
           </sthead>
           <strow>
              <stentry translate="no" props="annotation">1</stentry>
              <stentry translate="no" props="part-name">P​L​A​S​T​I​C​S​ ​S​U​B​ ​A​S​Y​ ​-​ ​F​R​O​N​T​ ​F​A​S​C​I​A​ </stentry>
              <stentry translate="no" props="part-number">1008590-00-D</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry/>
           </strow>
           <strow>
              <stentry translate="no" props="annotation">1</stentry>
              <stentry translate="no" props="part-name">P​L​A​S​T​I​C​S​ ​S​U​B​ ​A​S​Y​ ​-​ ​F​R​O​N​T​ ​F​A​S​C​I​A​ ​W​/​ ​P​A​R​K​ ​A​S​S​I​S​T​ </stentry>
              <stentry translate="no" props="part-number">1030348-00-A</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry translate="yes" props="comment">With holes for park assist sensors</stentry>
           </strow>
           <strow>
              <stentry translate="no" props="annotation">2</stentry>
              <stentry translate="no" props="part-name">B​r​a​c​k​e​t​ ​F​e​n​d​e​r​ ​F​R​T​ ​F​a​s​c​i​a​ ​L​e​f​t</stentry>
              <stentry translate="no" props="part-number">6005888-00-D</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry/>
           </strow>
           ...
</simpletable>

我试图编写一个比较两个XML之间的部件号的XSLT。如果它们相等,则将部件名称从XML#1写入XML#2。所以,结果将是:

<simpletable relcolwidth="5* 40* 15* 5* 35*">
           <sthead translate="yes">
              <stentry>No.</stentry>
              <stentry>Part Description</stentry>
              <stentry>Part Number</stentry>
              <stentry>Qty</stentry>
              <stentry>Comments</stentry>
           </sthead>
           <strow>
              <stentry translate="no" props="annotation">1</stentry>
              <stentry translate="no" props="part-name">​Another test</stentry>
              <stentry translate="no" props="part-number">1008590-00-D</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry/>
           </strow>
           <strow>
              <stentry translate="no" props="annotation">1</stentry>
              <stentry translate="no" props="part-name">Still another test</stentry>
              <stentry translate="no" props="part-number">1030348-00-A</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry translate="yes" props="comment">With holes for park assist sensors</stentry>
           </strow>
           <strow>
              <stentry translate="no" props="annotation">2</stentry>
              <stentry translate="no" props="part-name">B​r​a​c​k​e​t​ ​F​e​n​d​e​r​ ​F​R​T​ ​F​a​s​c​i​a​ ​L​e​f​t</stentry>
              <stentry translate="no" props="part-number">6005888-00-D</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry/>
           </strow>
           ...
</simpletable>

到目前为止我写的变换是不正确的,显然过于简单。模板不是按照我期望的方式迭代。

我的XSLT:

<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:output method="xml" encoding="UTF-8" indent="yes" doctype-system="reference.dtd" doctype-public="-//OASIS//DTD DITA Reference//EN"/>

<xsl:param name="removeAttributesNamed" select="'|domains|ditaarch:DITAArchVersion|class|'"/>
<xsl:variable name="inputDoc" select="document('output-test.xml')/descendant::stentry[@props='part-number']"/>
<xsl:variable name="outputDoc" select="document('BODY.xml')/descendant::stentry[@props='part-number']"/>

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

<xsl:template match="@*">
    <xsl:if test=
        "not(contains($removeAttributesNamed,
        concat('|', name(), '|')
        )
        )
        ">
        <xsl:call-template name="ref"/>
    </xsl:if>
</xsl:template>

<xsl:template name="combine">
    <xsl:choose>
        <xsl:when test="$inputDoc = $outputDoc">
            <stentry translate="yes" props="part-name">                
                <xsl:for-each  select="document('output-test.xml')/descendant::stentry[@props='part-name']">
                    <xsl:value-of select="text()"/>
                </xsl:for-each>                
            </stentry>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="."/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="stentry[@props='part-name']">
    <xsl:call-template name="combine"/>
</xsl:template>   

使用这个XSLT,我的结果是:

<simpletable relcolwidth="5* 40* 15* 5* 35*">
           <sthead translate="yes">
              <stentry>No.</stentry>
              <stentry>Part Description</stentry>
              <stentry>Part Number</stentry>
              <stentry>Qty</stentry>
              <stentry>Comments</stentry>
           </sthead>
           <strow>
              <stentry translate="no" props="annotation">1</stentry>
              <stentry translate="yes" props="part-name">This is a testAnother testStill another test</stentry>
              <stentry translate="no" props="part-number">1008590-00-D</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry/>
           </strow>
           <strow>
              <stentry translate="no" props="annotation">1</stentry>
              <stentry translate="yes" props="part-name">This is a testAnother testStill another test</stentry>
              <stentry translate="no" props="part-number">1030348-00-A</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry translate="yes" props="comment">With holes for park assist sensors</stentry>
           </strow>
           <strow>
              <stentry translate="no" props="annotation">2</stentry>
              <stentry translate="yes" props="part-name">This is a testAnother testStill another test</stentry>
              <stentry translate="no" props="part-number">6005888-00-D</stentry>
              <stentry translate="no" props="quantity">1</stentry>
              <stentry/>
           </strow>
           ...
</simpletable>

我看到的一个问题是看起来我比较节点序列而不是每个部件号的实际字符串值。但是我觉得我现在有点过头而且不确定我会怎么做。所以,我正在寻找一些指导,这将有助于我改进我那么粗糙的解决方案。

1 个答案:

答案 0 :(得分:0)

  

到目前为止,我所写的转变是不正确的   过于简单。

恕我直言,你过度复杂,不过分简化。

假设您正在处理标记为 XML#2 的文档,并假设另一个标记为 XML#1 的文档被命名为&#34 ; otherfile.xml&#34;,以下dstylesheet:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="part" match="strow" use="stentry[@props='part-number']" />

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

<xsl:template match="stentry[@props='part-name']">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:variable name="matching-part" select="key('part', ../stentry[@props='part-number'], document('otherfile.xml'))" />
        <xsl:choose>
            <xsl:when test="$matching-part">
                <xsl:value-of select="$matching-part/stentry[@props='part-name']"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

应该返回请求的结果。请注意使用来查找其他文件中的值。