xslt - 当这些内容由2个文件共享时,用引用替换内容

时间:2016-05-27 09:18:02

标签: xml file xslt

给定几个我称之为source1.xml的XML文件,例如(节点可能会有所不同):

源文件

<root id="s1">
    <title>example</title>
        <p>Some body text.</p>
        <div>
            <ul>
                <li>Some list item</li>
                <li>Some list item</li>
            </ul>
            <p>qqwerty</p>
            <p>asdfg</p>
        </div>
</root>

参考文件

我称之为reference1.xml的其他文件如下所示:

<root>    
    <div>
        <ul>
            <li>Some list item</li>
            <li>Some list item</li>
        </ul>
        <p>qqwerty</p>
        <p>asdfg</p>
     </div>
<root>

reference2.xml看起来像这样:

<root>    
    <div>
       <p>Some body text.<p>
    </div>
</root>    

每个文件中只能有一个div元素。

映射文件

要将这些映射到一起,我有一个如下所示的文件:

<references>  
   <input src="source1.xml" id="s1">
      <reference>T:\temp\reference1.xml</reference>
      <reference>T:\temp\reference2.xml</reference>
   </input>
</references>

预期结果

我想得到以下内容:

<root id="s1">
    <title>example</title>
        <link href="reference2.xml"/>
        <div>
            <link href="reference1.xml"/>
        </div>
</root>

所以我的想法是,我想看到div的{​​{1}}节点的整个内容可以在reference.xml中找到AS / IS,如果是,只需插入一个引用即可它在源头。它必须是“愚蠢的替换”,如果我找到它,我会在源中替换它,无论内容可能在哪里,无论父元素还是其他什么。

如果在源中只找到某些元素,则表示不行,不会创建任何链接。对于要创建的链接,它必须完全相同。

如何使用XSLT 2.0执行此操作?

现在,根据答案中建议的代码,我得到以下输出:

source.xml

而不是:

<root id="s1">
    <title>example</title>
        <link href="reference2.xml"/>
        <div>
            <link href="reference1.xml"/>
            <link href="reference1.xml"/>
            <link href="reference1.xml"/>
        </div>
</root>

1 个答案:

答案 0 :(得分:2)

如果只有一个元素要匹配,那么

<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:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:variable name="main-doc-uri" select="document-uri()"/>

    <xsl:param name="ref-list-doc-uri" select="'reference-list.xml'"/>
    <xsl:variable name="ref-list-doc" select="doc($ref-list-doc-uri)"/>

    <xsl:variable name="ref-docs" select="document($ref-list-doc/references/input[resolve-uri(@src) = $main-doc-uri]/reference)"/>

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

    <xsl:template match="*">
        <xsl:variable name="matched-doc" select="$ref-docs[ReusableComponent/ComponentDefinition/*[deep-equal(., current())]]"/>
        <xsl:choose>
            <xsl:when test="$matched-doc">
                <link href="{tokenize(document-uri($matched-doc), '/')[last()]}"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:next-match/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

应该足够了。

根据您对要求的编辑,我将样式表增强为

reference-list.xml

我假设<references> <input src="source1.xml"> <reference>ref1.xml</reference> <reference>ref2.xml</reference> </input> </references> 具有类似

的结构
<?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"
    version="2.0">

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

    <xsl:variable name="main-doc-uri" select="document-uri()"/>

    <xsl:param name="ref-list-doc-uri" select="'reference-list.xml'"/>
    <xsl:variable name="ref-list-doc" select="doc($ref-list-doc-uri)"/>

    <xsl:variable name="ref-docs" select="document($ref-list-doc/references/input[resolve-uri(@src) = $main-doc-uri]/reference)"/>

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

    <xsl:template match="*">
        <xsl:variable name="matched-doc" select="$ref-docs[*:ReusableComponent/*:ComponentDefinition/*[deep-equal(., current())]]"/>
        <xsl:choose>
            <xsl:when test="$matched-doc">
                <link href="{tokenize(document-uri($matched-doc), '/')[last()]}"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:next-match/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

但我没有尝试使用多个源文件和参考文件,因此您需要自己测试。

如果参考文档中可能使用不同的命名空间,那么可能使用通配符有助于:

<?xml version="1.0" encoding="UTF-8"?>
<root id="s1">
    <title>example</title>
    <p>Some body text.</p>
    <div>
        <ul>
            <li>Some list item</li>
            <li>Some list item</li>
        </ul>
    </div>
</root>

那样,输入

<?xml version="1.0" encoding="UTF-8"?>
<root id="s1">
   <title>example</title>
   <link href="reference201605270302.xml"/>
   <div>
      <link href="reference201605270301.xml"/>
   </div>
</root>

我得到了输出

resolve-uri(@src) = $main-doc-uri

根据id中URI的比较选择要加载的文档,如果您想根据<xsl:variable name="ref-docs" select="document($ref-list-doc/references/input[@id = $main-doc/*/@id]/reference)"/>属性执行此操作,那么我想您希望<xsl:variable name="main-doc" select="/"/>全局变量var contact = "+19876543210 (mobile)"; // If var contact = "09876543219 then its not working" contact.match(/^(\+?(\d{1,3}))?[-.\s]?\(?[1-9]\d{2}\)?[-.\s]?\d{3}[-.\s]?\d{4}/)