2

我想使用 XSLT 更新 XML 中的一些节点。喜欢联系方式和电子邮件。目前我正在使用如下命令:

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

<xsl:template match="/Metadata/contact/node/Email">    

      <xsl:variable name="OName" select="/Metadata/contact/organisationName/CharacterString"/>
      <xsl:variable name="Email" select="/Metadata/contact/node/Email/CharacterString"/>

          <xsl:choose>
            <xsl:when test="contains($OName,'TestOrg')">
              <CharacterString>
                <xsl:value-of select="'test@Test.com'"/>
              </CharacterString>
            </xsl:when>
            <xsl:otherwise>
              <CharacterString>
                <xsl:value-of select="$Email"/>
              </CharacterString>
            </xsl:otherwise>
          </xsl:choose>

  </xsl:template>

由于联系人节点是多个,并且在每个联系人节点中都有一个组织名称和电子邮件 ID。例如,联系人节点为 3,目前它在 $OName 变量和 $Email 变量中获取 3 个值,因此节点不匹配。那么如何使用 XSLT 只更新 xml 中的某些节点呢?

4

2 回答 2

1

您拥有的第一个模板是所谓的“身份模板”,它将遍历您的完整源 XML:

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

您拥有的第二个模板将匹配每个/Metadata/contact/node/Email. 我会写这个模板有点不同。而不是匹配绝对路径,我认为最好匹配Email/CharacterString节点然后执行您的操作。

我会使用这样的模板:

<xsl:template match="Email/CharacterString">
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="contains(ancestor::contact/organisationName/CharacterString,'TestOrg')">
                <xsl:value-of select="'test@Test.com'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

以上模板仅匹配您要更改的节点(正在Email/CharacterString)。一旦匹配xsl:copy副本当前选定的节点 ( CharacterString)。该值将根据 的值填充ancestor::contact/organisationName/CharacterString。我在这里使用XPath Ax ancestor。更改模板时会很方便。

如果我现在要更改模板,例如只选择我想更改的联系人节点,则第二个模板可以写为:

<xsl:template match="contact[organisationRole/CharacterString = '1']/node/Email/CharacterString">
    <xsl:copy>
        <xsl:choose>
            <xsl:when test="contains(ancestor::contact/organisationName/CharacterString,'TestOrg')">
                <xsl:value-of select="'test@Test.com'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

这里我只将模板应用于( ) 等于值 1 的contact节点。请注意,模板的主体没有改变。因此,您可以看到为什么使用XPath Ax是有用的。[]organisationRole/CharacterString

完整的 XSLT

<?xml version="1.0" encoding="UTF-8"?>
<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"/>

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

    <xsl:template match="contact[organisationRole/CharacterString = '1']/node/Email/CharacterString">
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="contains(ancestor::contact/organisationName/CharacterString,'TestOrg')">
                    <xsl:value-of select="'test@Test.com'"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

源 XML

<?xml version="1.0" encoding="UTF-8"?>
<Metadata>
    <contact>
        <organisationRole>
            <CharacterString>1</CharacterString>
        </organisationRole>
        <organisationName>
            <CharacterString>TestOrg</CharacterString>
        </organisationName>
        <postalCode>
            <CharacterString>2020</CharacterString>
        </postalCode>
        <node>
            <Email>
                <CharacterString>some@user.com</CharacterString>
            </Email>
        </node>
    </contact>
    <contact>
        <organisationRole>
            <CharacterString>2</CharacterString>
        </organisationRole>
        <organisationName>
            <CharacterString>Example Org</CharacterString>
        </organisationName>
        <postalCode>
            <CharacterString>8080</CharacterString>
        </postalCode>
        <node>
            <Email>
                <CharacterString>somebody@else.com</CharacterString>
            </Email>
        </node>
    </contact>
    <contact>
        <organisationRole>
            <CharacterString>1</CharacterString>
        </organisationRole>
        <organisationName>
            <CharacterString>Real Org</CharacterString>
        </organisationName>
        <postalCode>
            <CharacterString>9050</CharacterString>
        </postalCode>
        <node>
            <Email>
                <CharacterString>user@example.com</CharacterString>
            </Email>
        </node>
    </contact>
</Metadata>

产出

<?xml version="1.0" encoding="UTF-8"?>
<Metadata>
    <contact>
        <organisationRole>
            <CharacterString>1</CharacterString>
        </organisationRole>
        <organisationName>
            <CharacterString>TestOrg</CharacterString>
        </organisationName>
        <postalCode>
            <CharacterString>2020</CharacterString>
        </postalCode>
        <node>
            <Email>
                <CharacterString>test@Test.com</CharacterString>
            </Email>
        </node>
    </contact>
    <contact>
        <organisationRole>
            <CharacterString>2</CharacterString>
        </organisationRole>
        <organisationName>
            <CharacterString>Example Org</CharacterString>
        </organisationName>
        <postalCode>
            <CharacterString>8080</CharacterString>
        </postalCode>
        <node>
            <Email>
                <CharacterString>somebody@else.com</CharacterString>
            </Email>
        </node>
    </contact>
    <contact>
        <organisationRole>
            <CharacterString>1</CharacterString>
        </organisationRole>
        <organisationName>
            <CharacterString>Real Org</CharacterString>
        </organisationName>
        <postalCode>
            <CharacterString>9050</CharacterString>
        </postalCode>
        <node>
            <Email>
                <CharacterString>user@example.com</CharacterString>
            </Email>
        </node>
    </contact>
</Metadata>

编辑

如果您只想更改包含文本Email/CharacterString的联系人,XSLT 将如下所示:organisationName/CharacterStringTestOrg

<?xml version="1.0" encoding="UTF-8"?>
<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"/>

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

    <xsl:template match="contact[contains(organisationName/CharacterString,'TestOrg')]/node/Email/CharacterString">
        <xsl:copy>
            <xsl:value-of select="'test@Test.com'"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet> 
于 2014-02-24T07:49:04.043 回答
0

从您的描述看来,您的变量选择需要与模板的上下文节点相关:

<xsl:template match="/Metadata/contact/node/Email">    

  <xsl:variable name="OName" select="../../organisationName/CharacterString"/>
  <xsl:variable name="Email" select="CharacterString"/>

否则,您将始终从根节点开始为模板的每个匹配项进行选择,并且每次都将选择所有现有的联系人节点。

于 2014-02-24T07:24:36.037 回答