0

我有以下xml:

<PCstore>
    <StoreList>
        <Store id="001">
            <ItemList>
                <Items laptop="DELL" price="300"/>
                <Items laptop="gateway" price="450"/>
                <Items screen="LG" price="200"/>
            </ItemList>
        </Store>
    </StoreList>
</PCstore>

我必须合并:

<PCstore>
    <StoreList>
        <Store id="002">
            <ItemList>
                <Items laptop="gateway" price="650"/>
                <Items screen="LG" price="200/>
                <Items speakers="sony" price="50"/>
            </ItemList>
        </Store>
    </StoreList>
</PCstore>

以及过滤属性的期望输出(laptop="gateway"):

<PCstore>
    <StoreList>
        <Store id="001">
            <ItemList>
                <Items laptop="gateway" price="450"/>
            </ItemList>
        </Store>
        <Store id="002">
            <ItemList>
                <Items laptop="gateway" price="650"/>
            </ItemList>
        </Store>
    </StoreList>
</PCstore>

等等更多的xml3.xml,xml4.xml等......

我没有尝试过的代码,我对 XSLT 有点陌生,我希望有人可以帮助我。

更新

我试过这段代码,但它不工作......

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

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

  <xsl:template match="Items">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()" />
      <xsl:apply-templates
        select="document('xml2.xml')
              /PCstore/StoreList/Store/ItemList[@id = current()/../@id]
                     /Items[@laptop = current()/@value]/*" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
4

2 回答 2

1

如果只能使用 XSLT1.0,一种方法是将 xml 文件列表作为参数传递给 XSLT。例如:

<xsl:param name="filelist">
   <files>
      <file>xml2.xml</file>
      <!-- We can place here xml3.xml and so on -->
   </files>
</xsl:param>

(因此,在这种情况下,我假设您将 XSLT 应用于第一个 xml1.xml,并且您只将任何其他文件作为参数传递)。

但是,在 XSLT1.0 中,您将需要使用扩展函数来将此参数作为节点集进行处理。这样做<xsl:for-each select="$filelist/files/file">将导致错误“对变量或参数'文件'的引用必须评估为节点列表。 ”。因此,您将需要使用扩展函数将其转换为node-set。在我的示例中,我将使用 Microsoft 的示例,但根据您的平台,您可能会使用 exslt.org/common

在这种情况下,这是完整的 XSLT

<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:msxml="urn:schemas-microsoft-com:xslt" 
     extension-element-prefixes="msxml">

   <xsl:output omit-xml-declaration="yes" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:param name="filelist">
      <files>
         <file>xml2.xml</file>
      </files>
   </xsl:param>

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

   <xsl:template match="StoreList">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
         <xsl:for-each select="msxml:node-set($filelist)/files/file">
            <xsl:apply-templates select="document(text())/PCstore/StoreList/Store"/>
         </xsl:for-each>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="Items[not(@laptop='gateway')]"/>
</xsl:stylesheet>

当应用于您的 XSLT 时,它会输出以下内容

<PCstore>
   <StoreList>
      <Store id="001">
         <ItemList>
            <Items laptop="gateway" price="450"/>
         </ItemList>
      </Store>
      <Store id="002">
         <ItemList>
            <Items laptop="gateway" price="650"/>
         </ItemList>
      </Store>
   </StoreList>
</PCstore>

请注意,文件必须存在才能正常工作。如果传入一个不存在的文件名,就会出错。

于 2013-03-17T09:10:03.453 回答
0

如果您可以使用 XSLT 2.0,您可以使用collection()...

xml1.xml

<PCstore>
    <StoreList>
        <Store id="001">
            <ItemList>
                <Items laptop="DELL" price="300"/>
                <Items laptop="gateway" price="450"/>
                <Items screen="LG" price="200"/>
            </ItemList>
        </Store>
    </StoreList>
</PCstore>

xml2.xml

<PCstore>
    <StoreList>
        <Store id="002">
            <ItemList>
                <Items laptop="gateway" price="650"/>
                <Items screen="LG" price="200"/>
                <Items speakers="sony" price="50"/>
            </ItemList>
        </Store>
    </StoreList>
</PCstore>

XSLT 2.0

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

    <xsl:param name="type" select="'laptop'"/>
    <xsl:param name="brand" select="'gateway'"/>

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

    <xsl:template match="/">
        <PCstore>
            <StoreList>
                <xsl:apply-templates select="collection('file:///C:/store_test?select=*.xml')/PCstore/StoreList/Store"/>
            </StoreList>
        </PCstore>
    </xsl:template>

    <xsl:template match="Items[not(@*[name()=$type]=$brand)]"/>

</xsl:stylesheet>

输出

<PCstore>
   <StoreList>
      <Store id="001">
            <ItemList>

                <Items laptop="gateway" price="450"/>

            </ItemList>
        </Store>
      <Store id="002">
            <ItemList>
                <Items laptop="gateway" price="650"/>


            </ItemList>
        </Store>
   </StoreList>
</PCstore>
于 2013-03-17T02:19:09.963 回答