使用XSLT复制XML中的所有节点,同时转换具有特定兄弟值的节点

问题描述 投票:0回答:2

我有一个 xml 文件,除了需要转换的具有特定值的 1 个节点外,我主要需要 1 个复制 1 个。我的 XML 看起来像这样:

<?xml version='1.0' encoding='UTF-8'?>
<xyz:Workers xmlns:xyz="urn:com.website/xyz">
    <xyz:Worker>
        <xyz:Effective_Change xyz:Sequence="0">
            <xyz:Person_Identification xyz:isAdded="1">
                <xyz:Identifier>
                    <xyz:ID>MJ 12 34 56 Z</xyz:ID>
                    <xyz:IdType>A Type</xyz:IdType>
                </xyz:Identifier>
            </xyz:Person_Identification>
        </xyz:Effective_Change>
    </xyz:Worker>
    <xyz:Worker>
        <xyz:Effective_Change xyz:Sequence="0">
            <xyz:Person_Identification xyz:isUpdated="1">
                <xyz:Identifier xyz:isUpdated="1">
                    <xyz:ID>JHQ123</xyz:ID>
                    <xyz:IdType>B Type</xyz:IdType>
                </xyz:Identifier>
                <xyz:Identifier xyz:isUpdated="1">
                    <xyz:ID xyz:priorValue="555-55-5555">123-45-6789</xyz:ID>
                    <xyz:IdType>C Type</xyz:IdType>
                </xyz:Identifier>
            </xyz:Person_Identification>
        </xyz:Effective_Change>
    </xyz:Worker>
</xyz:Workers>

我需要获取加载到节点xyz:ID中的值

 <xyz:ID>MJ 12 34 56 Z</xyz:ID>

然后去掉空白,看起来像这样:

 <xyz:ID>MJ123456Z</xyz:ID>

但只有当他们的兄弟节点是xyz:IdType = A Type

 <xyz:IdType>A Type</xyz:IdType>

这是我试过的 XSLT。我引用了这个堆栈溢出(Using XSLT to copy all nodes in XML, with support for special cases)但是在处理它之后,我不确定这是否是正确的方法。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:this="urn:this-stylesheet"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:xyz="urn:com.website/xyz" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="xs this">
    <!--Identity template, 
        provides default behavior that copies all content into the output -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
   
    <xsl:template match="xyz:ID">  
        <xsl:copy>
            <xsl:value-of select="translate(node(), ' ', '')"/>
        </xsl:copy>
    </xsl:template> 
</xsl:stylesheet>

这个 XSLT 给我以下输出:

<?xml version="1.0" encoding="UTF-8"?><xyz:Workers xmlns:xyz="urn:com.website/xyz">
    <xyz:Worker>
        <xyz:Effective_Change xyz:Sequence="0">
            <xyz:Person_Identification xyz:isAdded="1">
                <xyz:Identifier>
                    <xyz:ID>MJ123456Z</xyz:ID>
                    <xyz:IdType>A Type</xyz:IdType>
                </xyz:Identifier>
            </xyz:Person_Identification>
        </xyz:Effective_Change>
    </xyz:Worker>
    <xyz:Worker>
        <xyz:Effective_Change xyz:Sequence="0">
            <xyz:Person_Identification xyz:isUpdated="1">
                <xyz:Identifier xyz:isUpdated="1">
                    <xyz:ID>JHQ123</xyz:ID>
                    <xyz:IdType>B Type</xyz:IdType>
                </xyz:Identifier>
                <xyz:Identifier xyz:isUpdated="1">
                    <xyz:ID>123-45-6789</xyz:ID>
                    <xyz:IdType>C Type</xyz:IdType>
                </xyz:Identifier>
            </xyz:Person_Identification>
        </xyz:Effective_Change>
    </xyz:Worker>
</xyz:Workers>

这接近于所需的输出,因为它确实从所需的 ID 中去除了空白:

 <xyz:ID>MJ123456Z</xyz:ID>

但是,在 C 类型标识符上,它正在删除标签中加载的数据:

改造前:

 
 <xyz:ID xyz:priorValue="555-55-5555">123-45-6789</xyz:ID>
 <xyz:IdType>C Type</xyz:IdType>
                 

改造后:

 <xyz:ID>123-45-6789</xyz:ID>
 <xyz:IdType>C Type</xyz:IdType>

这是一个问题,因为我希望文件的其余部分相同,除了 ID 的同级 ID 类型 = A 类型。

我相信这与将自身应用于所有 ID 节点的模板匹配有关。我试着按照这个逻辑做一些事情:

   <xsl:template match="xyz:Identifier[xyz:IdType='A Type']">  

但是没有运气。任何关于从哪里开始或我应该使用哪种逻辑的线索都将受到高度赞赏。

xml xslt xsd xslt-1.0 xslt-2.0
2个回答
1
投票

但只有当他们的兄弟节点是xyz:ID_Type = A Type

为此,您可以在

xyz:Identifier
上使用谓词。请注意,尽管您说的是
xyz:ID_Type
,但示例中有
xyz:IdType
.

我也只是匹配

text()
所以你不必复制或应用模板到
xyz:ID
的属性。

尝试将您的最后一个模板更改为(如果您的实际数据需要,将

IdType
更改为
ID_Type
):

<xsl:template match="xyz:Identifier[xyz:IdType='A Type']/xyz:ID/text()">
  <xsl:value-of select="translate(., ' ', '')"/>
</xsl:template> 

小提琴:http://xsltfiddle.liberty-development.net/nbUWwbs


1
投票

请尝试以下 XSLT。

看来你的 XML 样本应该有而不是:

<xyz:IdType>A Type</xyz:IdType>

以下内容:

<xyz:ID_Type>A Type</xyz:ID_Type>

XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xyz="urn:com.website/xyz">
    <xsl:output method="xml" indent="yes" encoding="utf-8"
                omit-xml-declaration="no"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="xyz:ID[following-sibling::xyz:ID_Type='A Type']">
        <xsl:copy>
            <xsl:value-of select="translate(., ' ', '')"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

输出

<?xml version='1.0' encoding='utf-8' ?>
<xyz:Workers xmlns:xyz="urn:com.website/xyz">
  <xyz:Worker>
    <xyz:Effective_Change xyz:Sequence="0">
      <xyz:Person_Identification xyz:isAdded="1">
        <xyz:Identifier>
          <xyz:ID>MJ123456Z</xyz:ID>
          <xyz:ID_Type>A Type</xyz:ID_Type>
        </xyz:Identifier>
      </xyz:Person_Identification>
    </xyz:Effective_Change>
  </xyz:Worker>
  <xyz:Worker>
    <xyz:Effective_Change xyz:Sequence="0">
      <xyz:Person_Identification xyz:isUpdated="1">
        <xyz:Identifier xyz:isUpdated="1">
          <xyz:ID>JHQ123</xyz:ID>
          <xyz:ID_Type>B Type</xyz:ID_Type>
        </xyz:Identifier>
        <xyz:Identifier xyz:isUpdated="1">
          <xyz:ID xyz:priorValue="555-55-5555">123-45-6789</xyz:ID>
          <xyz:ID_Type>C Type</xyz:ID_Type>
        </xyz:Identifier>
      </xyz:Person_Identification>
    </xyz:Effective_Change>
  </xyz:Worker>
</xyz:Workers>
© www.soinside.com 2019 - 2024. All rights reserved.