【问题标题】:Problem merging similar XML files with XSL将相似的 XML 文件与 XSL 合并时出现问题
【发布时间】:2011-02-15 14:47:59
【问题描述】:

我有两个需要合并的文档,它们的发生方式在其他示例中似乎无法找到。即,它不仅需要匹配上一级节点的属性,还需要匹配低于该节点级别的属性值,以获得该节点的值。

我正在尝试取样:

<?xml version="1.0" encoding="UTF-8" ?>
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <marc:record>
    <marc:datafield tag="035" ind1=" " ind2=" ">
        <marc:subfield code="a">12345</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="041" ind1=" " ind2=" ">
        <marc:subfield code="a">eng</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="650" ind1=" " ind2="4">
        <marc:subfield code="a">Art</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="949" ind1=" " ind2=" ">
        <marc:subfield code="i">Review of conference proceedings</marc:subfield>
    </marc:datafield>
  </marc:record>
  <marc:record>
    <marc:datafield tag="035" ind1=" " ind2=" ">
        <marc:subfield code="a">54321</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="041" ind1=" " ind2=" ">
        <marc:subfield code="a">eng</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="650" ind1=" " ind2="4">
        <marc:subfield code="a">Byzantine</marc:subfield>
    </marc:datafield>
  </marc:record>
</marc:collection>

当 "datafield" '035', "subfield" 'a' 的值匹配时,例如“12345”

<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <marc:record>
    <marc:datafield ind2=" " ind1=" " tag="035">
        <marc:subfield code="a">12345</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2="4" ind1=" " tag="650">
        <marc:subfield code="a">General works</marc:subfield>
        <marc:subfield code="x">Historians and critics</marc:subfield>
        <marc:subfield code="x">Smith, John, 1834-1917</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2="4" ind1=" " tag="650">
        <marc:subfield code="a">Généralités</marc:subfield>
        <marc:subfield code="x">Historiens et critiques d'art</marc:subfield>
        <marc:subfield code="x">Dietrichson, Lorentz, 1834-1917</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2=" " ind1=" " tag="654">
        <marc:subfield code="a">General works</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2=" " ind1=" " tag="654">
        <marc:subfield code="a">Généralités</marc:subfield>
        <marc:subfield code="b">Historiens et critiques d'art</marc:subfield>
        <marc:subfield code="b">Smith, John, 1834-1917</marc:subfield>
    </marc:datafield>
  </marc:record>      
  <marc:record>
    <marc:datafield ind2=" " ind1=" " tag="035">
        <marc:subfield code="a">54321</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2="4" ind1=" " tag="650">
        <marc:subfield code="a">General works</marc:subfield>
        <marc:subfield code="x">Historians and critics</marc:subfield>
        <marc:subfield code="x">Lange, Julius Henrik, 1838-1896</marc:subfield>
    </marc:datafield>
  </marc:record>
</marc:collection>

结果应该是:

<?xml version="1.0" encoding="UTF-8" ?>
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <marc:record>
    <marc:datafield tag="035" ind1=" " ind2=" ">
        <marc:subfield code="a">12345</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="041" ind1=" " ind2=" ">
        <marc:subfield code="a">eng</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="650" ind1=" " ind2="4">
        <marc:subfield code="a">Art</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2="4" ind1=" " tag="650">
        <marc:subfield code="a">General works</marc:subfield>
        <marc:subfield code="x">Historians and critics</marc:subfield>
        <marc:subfield code="x">Smith, John, 1834-1917</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2="4" ind1=" " tag="650">
        <marc:subfield code="a">Généralités</marc:subfield>
        <marc:subfield code="x">Historiens et critiques d'art</marc:subfield>
        <marc:subfield code="x">Dietrichson, Lorentz, 1834-1917</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2=" " ind1=" " tag="654">
        <marc:subfield code="a">General works</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2=" " ind1=" " tag="654">
        <marc:subfield code="a">Généralités</marc:subfield>
        <marc:subfield code="b">Historiens et critiques d'art</marc:subfield>
        <marc:subfield code="b">Smith, John, 1834-1917</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="949" ind1=" " ind2=" ">
        <marc:subfield code="i">Review of conference proceedings</marc:subfield>
    </marc:datafield>
  </marc:record>
  <marc:record>
    <marc:datafield tag="035" ind1=" " ind2=" ">
        <marc:subfield code="a">54321</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="041" ind1=" " ind2=" ">
        <marc:subfield code="a">eng</marc:subfield>
    </marc:datafield>
    <marc:datafield tag="650" ind1=" " ind2="4">
        <marc:subfield code="a">Byzantine</marc:subfield>
    </marc:datafield>
    <marc:datafield ind2="4" ind1=" " tag="650">
        <marc:subfield code="a">General works</marc:subfield>
        <marc:subfield code="x">Historians and critics</marc:subfield>
        <marc:subfield code="x">Lange, Julius Henrik, 1838-1896</marc:subfield>
    </marc:datafield>
  </marc:record>
</marc:collection>

我尝试使用我发现的可以进行查找的示例,但它们似乎都不起作用。我没有包含任何 XSL,因为我的所有结果都是灾难性的。我一直在看它,好像它一定很简单,但我只是没有得到任何体面的结果。任何帮助或指点将不胜感激。

谢谢!

【问题讨论】:

    标签: xml xslt merge marc


    【解决方案1】:

    以下解决方案使用键在合并文档中进行高效查找。假设应复制除匹配的datafield 之外的所有datafield 元素,并且每个record 最多有一个匹配的datafield。应该合并的文档的 URL 作为参数传递。

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:marc="http://www.loc.gov/MARC21/slim">
        <xsl:output method="xml" indent="yes"/>
        <xsl:param name="mergeFile"/>
        <xsl:variable name="mergeDoc" select="document($mergeFile)"/>
    
        <xsl:key name="datafield" match="marc:datafield" 
            use="concat(@tag, '|', marc:subfield[@code='a'])"/>
    
        <xsl:template match="/">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:template>
    
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="marc:record">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
                <xsl:apply-templates select="marc:datafield" mode="merge"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="marc:datafield" mode="merge">
            <xsl:variable name="datafieldKey" 
                          select="concat(@tag, '|', marc:subfield[@code='a'])"/>
            <!-- Make the other document the context node with for-each, so that
                 key lookups will consult that document instead of the source 
                 document. -->
            <xsl:for-each select="$mergeDoc">
                <xsl:for-each select="key('datafield', $datafieldKey)">
                    <xsl:copy-of select="preceding-sibling::*"/>
                    <xsl:copy-of select="following-sibling::*"/>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

      【解决方案2】:

      我想我有一个答案给你。它不是最优雅的,但它确实有效。基本上,您针对您尝试合并的一个 XML 文件运行样式表,然后使用文档函数来访问另一个 XML 文件。遍历第一个 XML 文件中的每条记录并找到匹配点。然后遍历第二个文档,找到匹配的记录,把合适的节点拉进去。

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

      <xsl:variable name="doc2" select="document('FourBabyMarcs.xml')"/>
      
      <xsl:template match="/">
          <marc:collection>
              <xsl:for-each select="marc:collection/marc:record">
                  <marc:record>
      
                      <xsl:for-each select="marc:leader">
                          <xsl:copy-of select="."/>
                      </xsl:for-each>
      
                      <xsl:for-each select="marc:controlfield">
                          <xsl:copy-of select="."/>
                      </xsl:for-each>
      
                      <xsl:for-each select="marc:datafield">
                          <xsl:copy-of select="."/>
                      </xsl:for-each>
      
                      <xsl:variable name="ID">
                          <xsl:value-of select="marc:datafield[@tag='035']/marc:subfield[@code='a']"/>
                      </xsl:variable>
      
                      <xsl:for-each select="$doc2/*/marc:record">
                              <xsl:if test="marc:datafield[@tag='035']/marc:subfield[@code='a']=$ID">
                                  <xsl:for-each select="marc:datafield">
                                      <xsl:if test="@tag='650'">
                                          <xsl:copy-of select="."/>
                                      </xsl:if>
                                      <xsl:if test="@tag='654'">
                                          <xsl:copy-of select="."/>
                                      </xsl:if>
                                  </xsl:for-each>
                              </xsl:if>
                      </xsl:for-each>
                  </marc:record>
              </xsl:for-each>
          </marc:collection>
      </xsl:template>
      

      【讨论】:

        猜你喜欢
        • 2013-02-05
        • 1970-01-01
        • 2011-06-13
        • 1970-01-01
        • 2012-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多