将值从一个xml文件合并到另一个。

时间:2018-09-30 13:48:13

标签: xml xslt attributes xslt-2.0 transformation

我有以下xml文件(我们将其称为parag.xml和句子.xml)。

Paragraph.xml

<?xml version="1.0" encoding="UTF-8"?>
<paragraphs>
     <paragraph id="par_1" parBegin="1" parEnd="100" par_type="intro" context="positive"/>
     <paragraph id="par_2" parBegin="101" parEnd="170" par_type="elaboration" context="negative"/>
     <paragraph id="par_3" parBegin="171" parEnd="210" par_type="elaboration" context="positive"/>
     <paragraph id="par_4" parBegin="211" parEnd="280" par_type="conclusion" context="neutral"/>

在paragraph.xml文件中,属性“ parBegin ”显示该段落开头的单词编号,而“ parEnd ”显示该段落所在单词的编号结束。例如,第一段元素以单词 1 (parBegin属性的值)开头,以单词 100 (第一段包含100个单词)结束。

另一个xml文件 sentence.xml 具有有关同一文本的句子的信息。

<?xml version="1.0" encoding="UTF-8"?>
 <sentences>
     <sentence id="sent_1" sentBegin="1" sentEnd="15" sent_type="question"/>
     <sentence id="sent_2" sentBegin="16" sentEnd="30" sent_type="imperative"/>
     <sentence id="sent_3" sentBegin="31" sentEnd="37" sent_type="confirmation"/>
     ...
     <sentence id="sent_15" sentBegin="120" sentEnd="125" sent_type="conclusion" />

在句子.xml文件中,属性“ sentBegin ”显示该句子开头的单词编号,而“ sentEnd ”显示该段落所在单词的编号结束。例如,第一个句子元素以单词 1 (sendBegin属性的值)开头,并以单词 15 结尾。带有 id =“ sent_15” 的句子以单词120(sentBegin =“ 120”)开头,并以单词125(sentEnd =“ 125”)结尾。

我要做的是检查每个句子属于哪个段落。换句话说,将属性 @sentEnd 的值与属性 @parEnd 。如果 @sentEnd 大于段落元素的 @parBegin 而小于 @parEnd ,则表明该句子属于该段落。例如,句子(id =“ sent_15”)的sendEnd值为125( sentEnd =“ 125” ),它大于 @parBegin (parBegin = id =“ par_2” 且小于其 @parEnd (parEnd =“ 170”)值的段落的“ 101”)值。这表明句子 id =“ sent_15” 属于段落 id =“ par_2” 。所需的输出如下所示:

<?xml version="1.0" encoding="UTF-8"?>
 <sentences>
     <sentence id="sent_1" sentBegin="1" sentEnd="15" sent_type="question" paragraph="par_1" par_type="intro"/>
     <sentence id="sent_2" sentBegin="16" sentEnd="30" sent_type="imperative" paragraph="par_1" par_type="intro"/>
     <sentence id="sent_3" sentBegin="31" sentEnd="37" sent_type="confirmation" paragraph="par_1" par_type="intro"/>
     ...
     <sentence id="sent_15" sentBegin="120" sentEnd="125" sent_type="conclusion" paragraph="par_2" par_type="elaboration" />

非常感谢您的反馈/解决方案。

1 个答案:

答案 0 :(得分:1)

您似乎可以简单地选择带有谓词的paragraph

  <xsl:template match="sentence">
      <xsl:copy>
          <xsl:apply-templates 
             select="@*, 
                     $paragraph-doc/paragraphs/paragraph[xs:integer(@parBegin) &lt;= xs:integer(current()/@sentBegin) and xs:integer(@parEnd) >= xs:integer(current()/@sentEnd)]/(@id, @par_type)"/>
      </xsl:copy>
  </xsl:template>

在下面,我已将段落文档内联到参数中,但是您当然可以使用doc函数来加载它:

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

  <xsl:param name="paragraph-doc">
    <paragraphs>
         <paragraph id="par_1" parBegin="1" parEnd="100" par_type="intro" context="positive"/>
         <paragraph id="par_2" parBegin="101" parEnd="170" par_type="elaboration" context="negative"/>
         <paragraph id="par_3" parBegin="171" parEnd="210" par_type="elaboration" context="positive"/>
         <paragraph id="par_4" parBegin="211" parEnd="280" par_type="conclusion" context="neutral"/>
    </paragraphs>
  </xsl:param>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="sentence">
      <xsl:copy>
          <xsl:apply-templates 
             select="@*, 
                     $paragraph-doc/paragraphs/paragraph[xs:integer(@parBegin) &lt;= xs:integer(current()/@sentBegin) and xs:integer(@parEnd) >= xs:integer(current()/@sentEnd)]/(@id, @par_type)"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="paragraph/@id">
      <xsl:attribute name="paragraph" select="."/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/nc4NzQZ是XSLT 3示例,对于XSLT 2,您需要用身份转换模板替换使用过的xsl:mode声明。

作为上述的改进或替代方案,我们可以在paragraph上键入@parBegin to @parEnd元素,然后使用该键从句子中找到相关的段落:

<?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="#all"
    version="3.0">

  <xsl:param name="paragraph-doc">
    <paragraphs>
         <paragraph id="par_1" parBegin="1" parEnd="100" par_type="intro" context="positive"/>
         <paragraph id="par_2" parBegin="101" parEnd="170" par_type="elaboration" context="negative"/>
         <paragraph id="par_3" parBegin="171" parEnd="210" par_type="elaboration" context="positive"/>
         <paragraph id="par_4" parBegin="211" parEnd="280" par_type="conclusion" context="neutral"/>
    </paragraphs>
  </xsl:param>

  <xsl:key name="par-ref" match="paragraph" use="@parBegin to @parEnd"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="sentence">
      <xsl:copy>
          <xsl:apply-templates 
             select="@*, 
                     key('par-ref', xs:integer(@sentEnd), $paragraph-doc)/(@id, @par_type)"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="paragraph/@id">
      <xsl:attribute name="paragraph" select="."/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/nc4NzQZ/2