简体   繁体   English

如何使用XSLT1.0在XML文件中替换ID元素及其所有参考元素

[英]How can I replace an ID element AND all of its reference elements in an XML file using XSLT1.0

I need to shorten some ID values and their references in an XML document using only XSLT... 我只需要使用XSLT缩短XML文档中的一些ID值及其引用。

Example XML doc: XML文档示例:

<root>
 <firstChild>
  <ID>99999</ID>
 </firstChild>
 <secondChild>
  <IDRef>99999</IDRef>
 </secondChild>
 <thirdChild>
  <person>
   <IDRef>99999</IDRef>
  </person>
 </thirdChild>
</root>

Desired result after applying XSLT: 应用XSLT后所需的结果:

<root>
 <firstChild>
  <ID>1</ID>
 </firstChild>
 <secondChild>
  <IDRef>1</IDRef>
 </secondChild>
 <thirdChild>
  <person>
   <IDRef>1</IDRef>
  </person>
 </thirdChild>
</root>

Basically I need XSLT to find each ID tag, replace it with a value and then find any IDRef tags elsewhere in the document and replace those with the same as the ID tag. 基本上,我需要XSLT来找到每个ID标记,将其替换为一个值,然后在文档中的其他位置找到任何IDRef标记,然后将其替换为与ID标记相同的标记。

Edit - The replacement value needs to be an incrementing number. 编辑-替换值必须是一个递增数字。 I think that the best way to make it increment would be to do something with the position() function in xslt. 我认为使它递增的最好方法是对xslt中的position()函数进行操作。 For example: 例如:

<xsl:variable name="ReplacementID" Select="position()"/>

I am not too concerned with how to make the numbers increment at this stage, I am more concerned with how to (if it is possible): 1. match an ID tag, change its text node to a new value, 2. then match any IDRef nodes and replace their text with the same value as what was added to the ID tag in step 1 The value itself could be anything from a global variable to a param that is passed into the stylesheet. 我不太关心如何在此阶段增加数字,我更关心如何(如果可能):1.匹配一个ID标记,将其文本节点更改为新值,然后2.匹配任何IDRef节点,并用与在步骤1中添加到ID标记中的值相同的值替换其文本。该值本身可以是任何值,从全局变量到传递到样式表的参数。

Below is a very rough XSLT of what I am trying to do (it does not work) 以下是我要执行的操作的非常粗略的XSLT(它不起作用)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <xsl:apply-templates select="@* | node()"/>
</xsl:template>

<xsl:template match="root/firstChild/ID">
    <xsl:variable name="currentID" select="."/>
    <xsl:variable name="replacementID">1</xsl:variable>
    <ID>
        <xsl:value-of select="$replacementID"/>
    </ID>
    <xsl:apply-templates select="IDRef[text() = $currentID]" mode="Replace">
        <xsl:with-param name="Replacement" select="$replacementID"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="IDRef" mode="Replace">
    <xsl:param name="Replacement"/>
    <IDRef>
        <xsl:value-of select="$Replacement"/>
    </IDRef>
</xsl:template>

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

How about: 怎么样:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="id" match="ID" use="." />

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

<xsl:template match="ID">
    <xsl:copy>
        <xsl:value-of select="count(preceding::ID) + 1" />
    </xsl:copy>
</xsl:template>

<xsl:template match="IDRef">
    <xsl:copy>
        <xsl:value-of select="count(key('id', .)/preceding::ID) + 1" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Applied to the following test input: 应用于以下测试输入:

<root>
    <master>
        <ID>12345</ID>
    </master>
    <slave>
        <IDRef>12345</IDRef>
    </slave>
    <element>
        <slave>
            <IDRef>987</IDRef>
        </slave>
    </element>
    <master>
        <ID>987</ID>
    </master>
    <slave>
        <IDRef>987</IDRef>
    </slave>
    <element>
        <slave>
            <IDRef>12345</IDRef>
        </slave>
    </element>
</root>

the result is: 结果是:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <master>
      <ID>1</ID>
   </master>
   <slave>
      <IDRef>1</IDRef>
   </slave>
   <element>
      <slave>
         <IDRef>2</IDRef>
      </slave>
   </element>
   <master>
      <ID>2</ID>
   </master>
   <slave>
      <IDRef>2</IDRef>
   </slave>
   <element>
      <slave>
         <IDRef>1</IDRef>
      </slave>
   </element>
</root>

-- -
BTW, I don't quite see what purpose the shortening of ID values serves; 顺便说一句,我不太清楚ID值缩短的目的是什么; as long as they are unique, who cares how long they are? 只要它们是独特的,谁在乎它们有多长时间?


I am more concerned with how to (if it is possible): 1. match an ID tag, change its text node to a new value, 2. then match any IDRef nodes and replace their text with the same value as what was added to the ID tag in step 1 我更关心如何(如果可能):1.匹配一个ID标记,将其文本节点更改为新值,2.然后匹配任何IDRef节点,并将其文本替换为与添加的文本相同的值步骤1中的ID标签

Well, it really depends on how exactly step 1 is performed. 好吧,这实际上取决于步骤1的执行情况。 Because the IDRef can always get to the original ID element in the source document - but not to its transformed counterpart in the result tree. 因为IDRef始终可以获取源文档中的原始ID元素-但无法获取其在结果树中转换后的对应元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM